4 puanın bir kare oluşturup oluşturmadığını belirleme


29

Düzlemde 4 puan alan ve 4 puan bir kare oluşturursa true değerini döndüren bir fonksiyon yazın. Noktalar, <1000 mutlak değerlerle integral koordinatlara sahip olacaktır.

4 noktanın herhangi bir makul gösterimini giriş olarak kullanabilirsiniz. Noktalar belirli bir sırada verilmez.

En kısa kod kazanır.

Örnek kareler:

(0,0),(0,1),(1,1),(1,0)    # standard square
(0,0),(2,1),(3,-1),(1,-2)  # non-axis-aligned square
(0,0),(1,1),(0,1),(1,0)    # different order

Örnek kareler olmayan:

(0,0),(0,2),(3,2),(3,0)  # rectangle
(0,0),(3,4),(8,4),(5,0)  # rhombus
(0,0),(0,0),(1,1),(0,0)  # only 2 distinct points
(0,0),(0,0),(1,0),(0,1)  # only 3 distinct points

Dejenere kare için doğru ya da yanlış döndürebilirsiniz (0,0),(0,0),(0,0),(0,0)


Burada 3B noktalardan bahsediyoruz değil mi?
gnibbler

3
@gnibbler "konulu soru marka 3D düzlemine" kısmı olası işaret ediyor.
JB

Puanlar verilen sırada mı?
JB

@JB, puanların bir uçakta olduğu anlamına geldiğini düşünüyordum, ama bir nedenle 3B alanda bir uçağı görselleştirdim :)
gnibbler

1
@ eBusiness: -1, 11 oy kullanmışsınız: 7'si aşağı.
Eelvex

Yanıtlar:


12

Python 176 90 79 bayt

def S(A):c=sum(A)/4.0;return set(A)==set((A[0]-c)\*1j\*\*i+c for i in range(4))

S işlevi girişi (A) olarak karmaşık sayıların bir listesini alır. Hem karenin merkezini hem de bir köşesini biliyorsak, köşeyi merkez noktasının (c) etrafında 90, 180 ve 270 derece döndürerek kareyi yeniden yapılandırabiliriz. Kompleks düzlemde başlangıç ​​noktası 90 derece döndürülerek nokta i ile çarpılarak yapılır . Orijinal şeklimiz ve yeniden oluşturulmuş karemiz aynı noktalara sahipse, o zaman bir kare olmalı.


Birkaç optimizasyon: 1) "is_square" yerine "S" kullanın. 2) hepsini kullanarak bir satıra yerleştirin; 3) doğrudan "i ((1,1j, -1, -1j)" i) için 4 yönün üzerinde yineleyin "4) set argümanında [] gerekmez.
Keith Randall

Sağol Keith. (
Kodumla

2
@Keith Randall - JB çok daha kısa bir çözümü olduğunda bu neden kabul edildi?
aaaaaaaaaaaa

1
İki sebep. Bir, J her zaman kazanırdı. Bu yüzden biraz dili normalleştirmek istiyorum. Ayrıca, bu cevabı daha çok seviyorum çünkü diğer rakamların (kuşkusuz, sadece mantıksız olanların) yanlış pozitif verdiği sadece mesafeli cevaplarla aynı problemden muzdarip değil.
Keith Randall

5
@Keith Randall - Sorudan alıntılar: "Noktaların integral koordinatlarına sahip olacak" "En kısa kod kazanır.". Bir cevap seçmek için farklı ölçütler seçerseniz, öznel ölçütler olsa bile, gayet iyi, ama o zaman bunu soruda belirtmelisiniz.
aaaaaaaaaaaa

13

J, 28 17 25 27

J gerçekten fonksiyonlara sahip değildir, ancak işte karmaşık düzlemden bir nokta vektör alan bir monadik fiil:

4 8 4-:#/.~&(/:~&:|&,&(-/~))

Metot, Michael Spencer'ın (sadece bölgeler arası uzunluklarda çalışır; ancak şu anda eşkenar dörtgenim2 üzerinde başarısız oluyor) ve Eelvex'in (setlerin boyutlarını kontrol et) çalışmasının bir karışımı . Sağdan sola okuma:

  • -/~ tüm nokta farklarını hesapla
  • , düzleştirmek
  • | büyüklüğü çıkarmak
  • /:~ Sırala
  • #/.~ nub ve say
  • 4 8 4 -:Tam olarak 4 eşit (0'da), 8 biraz daha büyük (uzunluk 1, yanlar), 4 daha büyük (uzunluk sqrt 2, diyagonaller) olmalıdır

gösteri:

   NB. give the verb a name for easier use
   f =: 4 8 4-:#/.~&(/:~&:|&,&(-/~))

   NB. standard square
   f 0 0j1 1j1 1
1

   NB. non-axis-aligned square
   f 0 2j1 3j_1 1j_2
1

   NB. different order
   f 0 1j1 0j1 1
1

   NB. rectangle
   f 0 0j2 3j2 3
0

   NB. rhombus 1
   f 0 3j4 8j4 5
0

   NB. rhombus 2
   f 0 1ad_60 1ad0 1ad60
0

Hafızanın iyiliği için önceki yöntemim (gerekli sipariş edilen köşeler, ancak herhangi bir siparişin düzenli çokgenlerini saptayabilir):

*./&(={.)&(%1&|.)&(-1&|.)

Açıklama ve demo için geçmişe bakınız. Mevcut yöntem muhtemelen 4 8 4bir binom dağılımına çok benzeyen diğer poligonlara genişletilebilir .


Bu dile link verebilir misiniz?
Sargun Dhillon

1
@gnibbler: Neden olmasın? Olduğundan eminim.
Eelvex

1
Aslında, kontrol ettiğiniz koşulları sağlayan kare olmayan bir rakam var, normal bir üçgen artı uzatılmış ortancaya yerleştirilmiş üçgenin bir ucundan bir yan uzunlukta. Ancak tamsayı girişi için sorulan soru, bu yüzden çözüm tamam.
aaaaaaaaaaaa 11:11

1
Ah tamam. Dördüncü nokta merkez olan eşkenar üçgenleri düşünüyordum, ancak bu tamsayı koordinatları tarafından
dışlandı

1
Açık bir tanımlamaya değiştirerek 3 karakter kesebilirsin: 3 :'4 8 4-:#/.~/:~|,-/~y'
isawdrones

5

Python, 71 42

lambda A: len(set(A))==4 and len(set(abs(i-j)for i in A for j in A))==3

Güncelleme 1) 4 farklı nokta gerektirmesi (daha önce tekrarlanan puanlar için yanlış pozitif verir miydi - diğerleri var mı?) 2) Spesifikasyon başına bir işlev tanımlamak için

Bir kare için, iki nokta arasındaki vektör 0 (aynı nokta), bir taraf veya çapraz olmalıdır. Bu nedenle, bu vektörlerin büyüklüğü kümesinin uzunluğu 3 olmalıdır.

# Accepts co-ordinates as sequences of complex numbers

SQUARES=[
 (0+0j,0+1j,1+1j,1+0j),  # standard square
 (0+0j,2+1j,3-1j,1-2j),  # non-axis-aligned square
 (0+0j,1+1j,0+1j,1+0j)   # different order
]

NONSQUARES=[
 (0+0j,0+2j,3+2j,3+0j),  # rectangle
 (0+0j,3+4j,8+4j,5+0j),  # rhombus
 (0+0j,0+1j,1+1j,0+0j),   # duplicated point
 (0+0j,1+60j,1+0j,1-60j)  # rhombus 2 (J B)
] 

test = "lambda A: len(set(A))==4 and len(set(abs(i-j)for i in A for j in A))==3"
assert len(test)==71

is_square=lambda A: len(set(A))==4 and len(set(abs(i-j)for i in A for j in A))==3    

for A in SQUARES:
    assert is_square(A)

for A in NONSQUARES:
    assert not is_square(A)

Sanırım soru açıkça bir vektör değil, bir nokta listesi belirtti.
Sargun Dhillon

Yanlış pozitifler.
aaaaaaaaaaaa

1
Yani (0 + 0j, 0 + 0j, 1 + 0j, 0 + 1j) kare mi?
mhagger

Eşkenar dörtgen 2, 1 +/- 60j değil , -1, 0, 1 arasındaki değerler için exp (i j pi / 3) gibidir. Sorunun kapsamı.
JB

3

Haskell, 100 karakter

İşte JB'in J çözümünü Haskell'de nasıl yazarım. Gerekli olmayan karakterleri kaldırarak okunabilirliğe zarar verme denemesi olmadan, yaklaşık 132 karakterdir:

import Data.List
d (x,y) (x',y') = (x-x')^2 + (y-y')^2
square xs = (== [4,8,4]) . map length . group . sort $ [d x y | x<-xs, y<-xs]

Fazla boşluk bırakarak ve bazı şeyleri yeniden adlandırarak, onu 100'e kadar kazıyabilirsiniz.

import Data.List
d(x,y)(a,b)=(x-a)^2+(y-b)^2
s l=(==[4,8,4]).map length.group.sort$[d x y|x<-l,y<-l]

Bir kareyi (x, y) ve kenar vektörü (a, b) ile rasgele kareleri kabul etmesini sağlamak için QuickCheck'i kullanalım:

prop_square (x,y) (a,b) = square [(x,y),(x+a,y+b),(x-b,y+a),(x+a-b,y+b+a)]

Ghci'de denemek:

ghci> quickCheck prop_square
*** Failed! Falsifiable (after 1 test):  
(0,0)
(0,0)

Doğru, boş kare burada kare sayılmaz, bu yüzden testimizi gözden geçireceğiz:

prop_square (x,y) (a,b) =
   (a,b) /= (0,0) ==> square [(x,y),(x+a,y+b),(x-b,y+a),(x+a-b,y+b+a)]

Ve tekrar deniyorum:

ghci> quickCheck prop_square
+++ OK, passed 100 tests.

1
Fonksiyonu kaldırarak 11 karakter kaydedin d. s l=[4,8,4]==(map length.group.sort)[(x-a)^2+(y-b)^2|(x,y)<-l,(a,b)<-l]
Ray

3

faktör

Faktör programlama dilinde bir uygulama :

USING: kernel math math.combinatorics math.vectors sequences sets ;

: square? ( seq -- ? )
    members [ length 4 = ] [
        2 [ first2 distance ] map-combinations
        { 0 } diff length 2 =
    ] bi and ;

Ve bazı birim testleri:

[ t ] [
    {
        { { 0 0 } { 0 1 } { 1 1 } { 1 0 } }   ! standard square
        { { 0 0 } { 2 1 } { 3 -1 } { 1 -2 } } ! non-axis-aligned square
        { { 0 0 } { 1 1 } { 0 1 } { 1 0 } }   ! different order
        { { 0 0 } { 0 4 } { 2 2 } { -2 2 } }  ! rotated square
    } [ square? ] all?
] unit-test

[ f ] [
    {
        { { 0 0 } { 0 2 } { 3 2 } { 3 0 } }   ! rectangle
        { { 0 0 } { 3 4 } { 8 4 } { 5 0 } }   ! rhombus
        { { 0 0 } { 0 0 } { 1 1 } { 0 0 } }   ! only 2 distinct points
        { { 0 0 } { 0 0 } { 1 0 } { 0 1 } }   ! only 3 distinct points
    } [ square? ] any?
] unit-test

3

OCaml, 145 164

let(%)(a,b)(c,d)=(c-a)*(c-a)+(d-b)*(d-b)
let t a b c d=a%b+a%c=b%c&&d%c+d%b=b%c&&a%b=a%c&&d%c=d%b
let q(a,b,c,d)=t a b c d||t a c d b||t a b d c

Bu şekilde koş:

q ((0,0),(2,1),(3,-1),(1,-2))

Biraz deobfuscate ve açıklayalım.

İlk önce bir norm tanımlarız:

let norm (ax,ay) (bx,by) = (bx-ax)*(bx-ax)+(by-ay)*(by-ay)

Sqrt çağrısı olmadığını fark edeceksiniz, burada gerekli değil.

let is_square_with_fixed_layout a b c d =
  (norm a b) + (norm a c) = norm b c
  && (norm d c) + (norm d b) = norm b c
  && norm a b = norm a c
  && norm d c = norm d b

Burada a, b, c ve d puandır. Bu noktaların bu şekilde düzenlendiğini varsayıyoruz:

a - b
| / |
c - d

Bir karemiz varsa, tüm bu koşullar geçerli olmalıdır:

  • abc dik bir üçgendir
  • bcd bir dik üçgendir
  • her sağ üçgenin küçük kenarları aynı normlara sahiptir

Aşağıdakilerin daima geçerli olduğunu gözlemleyin:

is_square_with_fixed_layout r s t u = is_square_with_fixed_layout r t s u

Bunu, aşağıdaki test fonksiyonumuzu basitleştirmek için kullanacağız.

Girişimiz sipariş edilmediğinden tüm izinleri de kontrol etmemiz gerekir. Genelliği kaybetmeden ilk noktaya izin vermekten kaçınabiliriz:

let is_square (a,b,c,d) =
  is_square_with_fixed_layout a b c d
  || is_square_with_fixed_layout a c b d
  || is_square_with_fixed_layout a c d b
  || is_square_with_fixed_layout a b d c
  || is_square_with_fixed_layout a d b c
  || is_square_with_fixed_layout a d c b

Basitleştirmeden sonra:

let is_square (a,b,c,d) =
  is_square_with_fixed_layout a b c d
  || is_square_with_fixed_layout a c d b
  || is_square_with_fixed_layout a b d c

Düzenleme: M.Giovannini'nin tavsiyesine uydu.


Güzel. Burada çok OCaml görmedim :)
Eelvex 11:11

Yerine bir operatörünü kullanın n20 karakter azaltılması için: let t a b c d=a%b+a%c=b%c&&d%c+d%b=b%c&&a%b=a%c&&d%c=d%b.
Matías Giovannini

2

Python (105)

Puanlar (x,y)perdelerle temsil edilir . Puanlar herhangi bir sırada olabilir ve sadece kareleri kabul eder. sNoktalar arasında ikili (sıfır olmayan) mesafeler içeren bir liste oluşturur . Toplamda iki ayrı grupta toplam 12 mesafe olmalıdır.

def f (p): s = filtre (Yok, [(xz) ** 2+ (yw) ** 2 için x, z için p için y, p] w,) return len (s) == 12 ve len ( grubu (ler)) == 2

Filtreyi dışarıda bırakabilir ve setin uzunluğunun 3 olup olmadığını kontrol edebilirsiniz. Bu benim cevabımla aynı yanlış pozitif sorundan muzdarip.
gnibbler

>>> f ([(0,0), (0,4), (2,2), (- 2,2)]) = Doğru
Sargun Dhillon

2
f([(0,0),(0,4),(2,2),(-2,2)]) bir kare
gnibbler

2

Python - 42 karakter

Puanlar için karmaşık sayıları kullanmak bir gelişme gibi görünüyor

len(set(abs(x-y)for x in A for y in A))==3

buradaki A = [(11 + 13j), (14 + 12j), (13 + 9j), (10 + 10j)]

eski cevap:

from itertools import*
len(set((a-c)**2+(b-d)**2 for(a,b),(c,d)in combinations(A,2)))==2

Noktalar herhangi bir sırayla liste halinde belirtilir, örn.

A = [(11, 13), (14, 12), (13, 9), (10, 10)]

>>> A=[(0,0),(0,0),(1,1),(0,0)] >>> len(set((a-c)**2+(b-d)**2 for(a,b),(c,d)in combinations(A,2)))==2 True
Sargun Dhillon

@Sargun, işe yaramayan bütün bir girdi sınıfı için özel bir durum. Cevabın boyutunu patlatmayan bir düzeltme düşünmeye çalışıyorum. Bu arada, başarısız sınıfların genel sınıflarını çözebilir mi?
gnibbler

A=[(0,0),(0,4),(2,2),(-2,2)]; len(set((a-c)**2+(b-d)**2 for(a,b),(c,d)in combinations(A,2)))==2
Sargun Dhillon

@Sargun: bu örnek bir kare.
Keith Randall

Kopyalanan noktalardan kurtulmak için -set ([0]) 'ı ekleyebilirsiniz
Keith Randall

2

Tam olarak kısa değil. LINQ kötüye kullanımı. Girişteki farklı iki nokta kombinasyonunu seçer, mesafelerini hesaplar, ardından tam olarak dördünün eşit olduğunu ve yalnızca bir tane daha farklı uzaklık değerinin olduğunu doğrular. Nokta iki çift üyeli bir sınıftır, X ve Y. Kolayca bir Tuple olabilir, ama meh.

var points = new List<Point>
             {
                 new Point( 0, 0 ), 
                 new Point( 3, 4 ), 
                 new Point( 8, 4 ), 
                 new Point( 5, 0 )
              };    
var distances = points.SelectMany(
    (value, index) => points.Skip(index + 1),
    (first, second) => new Tuple<Point, Point>(first, second)).Select(
        pointPair =>
        Math.Sqrt(Math.Pow(pointPair.Item2.X - pointPair.Item1.X, 2) +
                Math.Pow(pointPair.Item2.Y - pointPair.Item1.Y, 2)));
return
    distances.Any(
        d => distances.Where( p => p == d ).Count() == 4 &&
                distances.Where( p => p != d ).Distinct().Count() == 1 );

2

PHP, 82 karakter


//$x=array of x coordinates
//$y=array of respective y coordinates
/* bounding box of a square is also a square - check if Xmax-Xmin equals Ymax-Ymin */
function S($x,$y){sort($x);sort($y);return ($x[3]-$x[0]==$y[3]-$y[0])?true:false};

//Or even better (81 chars):
//$a=array of points - ((x1,y1), (x2,y2), (x3,y3), (x4,y4))
function S($a){sort($a);return (bool)($a[3][0]-$a[0][0]-abs($a[2][1]-$a[3][1]))};

Ancak sınırlayıcı kutunun kare olması, noktaların kare şeklinde olması anlamına gelmez. Gerekli fakat yeterli şart değil. (0,0), (5,5), (10,0), (0, -5) 'i düşünün. Sınırlayıcı kutu karedir (0:10, -5: 5); rakam değil.
Floris

2

K - 33

J çözümünün JB tarafından çevirisi :

{4 8 4~#:'=_sqrt+/'_sqr,/x-/:\:x}

K burada ayrılmış sözcüklerinden muzdariptir ( _sqrve _sqrt).

Test yapmak:

  f:{4 8 4~#:'=_sqrt+/'_sqr,/x-/:\:x}

  f (0 0;0 1;1 1;1 0)
1

  f 4 2#0 0 1 1 0 1 1 0
1

  f 4 2#0 0 3 4 8 4 5 0
0

2

OCaml + Pilleri, 132 karakter

let q l=match List.group(-)[?List:(x-z)*(x-z)+(y-t)*(y-t)|x,y<-List:l;z,t<-List:l;(x,y)<(z,t)?]with[[s;_;_;_];[d;_]]->2*s=d|_->false

(bak, Ma, boşluk yok!) Listedeki anlama, qher bir sıralanmamış nokta için kare normların listesini oluşturur. Bir kare dört eşit kenara ve iki eşit köşeye sahiptir, ikincisinin kare uzunlukları birincinin kare uzunluğunun iki katıdır. Tamsayılı kafesde eşkenar üçgenler olmadığından test gerçekten gerekli değildir, fakat ben bunu tamlık için ekliyorum.

Testler:

q [(0,0);(0,1);(1,1);(1,0)] ;;
- : bool = true
q [(0,0);(2,1);(3,-1);(1,-2)] ;;
- : bool = true
q [(0,0);(1,1);(0,1);(1,0)] ;;
- : bool = true
q [(0,0);(0,2);(3,2);(3,0)] ;;
- : bool = false
q [(0,0);(3,4);(8,4);(5,0)] ;;
- : bool = false
q [(0,0);(0,0);(1,1);(0,0)] ;;
- : bool = false
q [(0,0);(0,0);(1,0);(0,1)] ;;
- : bool = false

2

Mathematica 65 80 69 66

Noktalar arası mesafeli mesafelerin sayısının (bir noktadan kendisine olan mesafeyi içermeyen) 2 olduğunu ve ikisinin daha kısa olmadığını 0 kontrol eder.

h = Length@# == 2 \[And] Min@# != 0 &[Union[EuclideanDistance @@@ Subsets[#, {2}]]] &;

kullanım

h@{{0, 0}, {0, 1}, {1, 1}, {1, 0}}       (*standard square *)
h@{{0, 0}, {2, 1}, {3, -1}, {1, -2}}     (*non-axis aligned square *)
h@{{0, 0}, {1, 1}, {0, 1}, {1, 0}}       (*a different order *)

h@{{0, 0}, {0, 2}, {3, 2}, {3, 0}}       (* rectangle *)
h@{{0, 0}, {3, 4}, {8, 4}, {5, 0}}       (* rhombus   *)
h@{{0, 0}, {0, 0}, {1, 1}, {0, 0}}       (* only 2 distinct points *)
h@{{0, 0}, {0, 1}, {1, 1}, {0, 1}}       (* only 3 distinct points *)

Doğru
doğru
doğru
yanlış
yanlış
yanlış
yanlış

Not: \[And]Mathematica'da tek bir karakterdir.


1
Bana, Mathematica'nın yerleşik bir IsSquare işlevi olmadığını mı söylüyorsunuz?
goodguy

2

Jöle , 8 bayt

_Æm×ıḟƊṆ

Çevrimiçi deneyin!

Komut satırı argümanı olarak karmaşık sayılar listesini alır. 1Veya yazdırır 0.

_Æm        Subtract mean of points from each point (i.e. center on 0)
   ×ıḟƊ    Rotate 90°, then compute set difference with original.
       Ṇ   Logical negation: if empty (i.e. sets are equal) then 1 else 0.

Bu canlandırmak için eğlenceli bir meydan okuma gibi görünüyor!


1

Haskell (212)

import Data.List;j=any f.permutations where f x=(all g(t x)&&s(map m(t x)));t x=zip3 x(drop 1$z x)(drop 2$z x);g(a,b,c)=l a c==sqrt 2*l a b;m(a,b,_)=l a b;s(x:y)=all(==x)y;l(m,n)(o,p)=sqrt$(o-m)^2+(n-p)^2;z=cycle

Saf ilk girişimi. Girilen nokta listesinin tüm permütasyonları için aşağıdaki iki koşulu kontrol eder (belirli bir permütasyonun, saatlerin saat yönünde sıralanmasını temsil ettiği durumlarda):

  • tüm açılar 90 derecedir
  • her taraf aynı uzunluktadır

Kokulu kod ve testler

j' = any satisfyBothConditions . permutations
          --f
    where satisfyBothConditions xs = all angleIs90 (transform xs) && 
                                     same (map findLength' (transform xs))
          --t
          transform xs = zip3 xs (drop 1 $ cycle xs) (drop 2 $ cycle xs)
          --g
          angleIs90 (a,b,c) = findLength a c == sqrt 2 * findLength a b
          --m
          findLength' (a,b,_) = findLength a b
          --s
          same (x:xs) = all (== x) xs
          --l
          findLength (x1,y1) (x2,y2) = sqrt $ (x2 - x1)^2 + (y2 - y1)^2


main = do print $ "These should be true"
          print $ j [(0,0),(0,1),(1,1),(1,0)]
          print $ j [(0,0),(2,1),(3,-1),(1,-2)]
          print $ j [(0,0),(1,1),(0,1),(1,0)]
          print $ "These should not"
          print $ j [(0,0),(0,2),(3,2),(3,0)]
          print $ j [(0,0),(3,4),(8,4),(5,0)]
          print $ "also testing j' just in case"
          print $ j' [(0,0),(0,1),(1,1),(1,0)]
          print $ j' [(0,0),(2,1),(3,-1),(1,-2)]
          print $ j' [(0,0),(1,1),(0,1),(1,0)]
          print $ j' [(0,0),(0,2),(3,2),(3,0)]
          print $ j' [(0,0),(3,4),(8,4),(5,0)]

1

Ölçek (146 karakter)

def s(l:List[List[Int]]){var r=Set(0.0);l map(a=>l map(b=>r+=(math.pow((b.head-a.head),2)+math.pow((b.last-a.last),2))));print(((r-0.0).size)==2)}

1

JavaScript 144 karakter

J Bs cevabına matematiksel olarak eşit. 6 uzunluk üretir ve en büyük 2'nin eşit ve en küçük 4'ün eşit olduğunu iddia eder. Giriş bir dizi dizisi olmalıdır.

function F(a){d=[];g=0;for(b=4;--b;)for(c=b;c--;d[g++]=(e*e+f*f)/1e6)e=a[c][0]-a[b][0],f=a[c][1]-a[b][1];d.sort();return d[0]==d[3]&&d[4]==d[5]} //Compact function
testcases=[
[[0,0],[1,1],[1,0],[0,1]],
[[0,0],[999,999],[999,0],[0,999]],
[[0,0],[2,1],[3,-1],[1,-2]],
[[0,0],[0,2],[3,2],[3,0]],
[[0,0],[3,4],[8,4],[5,0]],
[[0,0],[0,0],[1,1],[0,0]],
[[0,0],[0,0],[1,0],[0,1]]
]
for(v=0;v<7;v++){
    document.write(F(testcases[v])+"<br>")
}

function G(a){ //Readable version
    d=[]
    g=0
    for(b=4;--b;){
        for(c=b;c--;){
            e=a[c][0]-a[b][0]
            f=a[c][1]-a[b][1]
            d[g++]=(e*e+f*f)/1e6 //The division tricks the sort algorithm to sort correctly by default method.
        }
    }
    d.sort()
    return (d[0]==d[3]&&d[4]==d[5])
}

1

PHP, 161 158 karakter

function S($a){for($b=4;--$b;)for($c=$b;$c--;){$e=$a[$c][0]-$a[$b][0];$f=$a[$c][1]-$a[$b][1];$d[$g++]=$e*$e+$f*$f;}sort($d);return$d[0]==$d[3]&&$d[4]==$d[5];}

Kanıt (1x1): http://codepad.viper-7.com/ZlBpOB

Bu, eBuisness'in JavaScript cevabına dayanmaktadır .


Sorunların açıklanmasında, puanların sıralanacağı kesin değil. Ben gidip soracağım.
JB

1
Bunun pek çok vakayı doğru bir şekilde halledeceğini sanmıyorum. Örneğin, eşkenar dörtgenleri yanlış şekilde kareler olarak etiketleyecektir.
Keith Randall

Bu, JavaScript cevaplarından biriyle eşleşmesi için güncellendi, tüm durumları ele almalı.
Kevin Brown

1

JavaScript 1.8, 112 karakter

Güncelleme: dizi kavramalarını birlikte katlayarak 2 karakter kaydetti.

function i(s)(p=[],[(e=x-a,f=y-b,d=e*e+f*f,p[d]=~~p[d]+1)for each([a,b]in s)for each([x,y]in s)],/8,+4/.test(p))

JB'in cevabının başka bir yeniden uygulaması. JavaScript 1.7 / 1.8 özelliklerini (ifade kapanışları, dizi kavramaları, yıkım ödevi). Ayrıca , dizi sayımdan zorlama ve uzunluk sayımlarının olup olmadığını kontrol etmek için bir regexp ile sayısal ~~olarak zorlamak undefinediçin (çift bit yönünde değil operatör) de kötüye kullanır ( [4, 8, 4]tam 4 puanın geçtiğini varsayar). Virgül operatörünün kötüye kullanılması eski bir karışık C hilesidir.

Testler:

function assert(cond, x) { if (!cond) throw ["Assertion failure", x]; }

let text = "function i(s)(p=[],[(e=x-a,f=y-b,d=e*e+f*f,p[d]=~~p[d]+1)for each([a,b]in s)for each([x,y]in s)],/8,+4/.test(p))"
assert(text.length == 112);
assert(let (source = i.toSource()) (eval(text), source == i.toSource()));

// Example squares:
assert(i([[0,0],[0,1],[1,1],[1,0]]))    // standard square
assert(i([[0,0],[2,1],[3,-1],[1,-2]]))  // non-axis-aligned square
assert(i([[0,0],[1,1],[0,1],[1,0]]))    // different order

// Example non-squares:
assert(!i([[0,0],[0,2],[3,2],[3,0]]))  // rectangle
assert(!i([[0,0],[3,4],[8,4],[5,0]]))  // rhombus
assert(!i([[0,0],[0,0],[1,1],[0,0]]))  // only 2 distinct points
assert(!i([[0,0],[0,0],[1,0],[0,1]]))  // only 3 distinct points

// Degenerate square:
assert(!i([[0,0],[0,0],[0,0],[0,0]]))   // we reject this case

1

GoRuby - 66 karakter

f=->a{z=12;a.pe(2).m{|k,l|(k-l).a}.so.go{|k|k}.a{|k,l|l.sz==z-=4}}

genişletilmiş:

f=->a{z=12;a.permutation(2).map{|k,l|(k-l).abs}.sort.group_by{|k|k}.all?{|k,l|l.size==(z-=4)}}

JB'in cevabıyla aynı algoritma .

Gibi test edin:

p f[[Complex(0,0), Complex(0,1), Complex(1,1), Complex(1,0)]]

trueDoğru ve yanlış için boş çıktılar


GoRuby'yi hiç duymadım. Bu konuda resmi bir yazı var mı? stackoverflow.com/questions/63998/hidden-features-of-ruby/…
Jonas Elfström

@Jonas: Bu konuda resmi olan hiçbir şey görmedim, gördüğüm en iyi blog yazısı bu . Aslında onu kurup çalıştıramazdım, ancak bir alternatif sadece golf başlığını aynı klasöre kopyalayıp çalıştırmak ruby -r ./golf-prelude.rb FILE_TO_RUN.rbve aynen aynı şekilde çalışacak.
Nemo157

daha sortönce gerekli değildir group_by. .sort.group_by {...}olarak yazılmalıdır.group_by {...}
user102008 25:11

1

Python 97 (karmaşık noktalar olmadan)

def t(p):return len(set(p))-1==len(set([pow(pow(a-c,2)+pow(b-d,2),.5)for a,b in p for c,d in p]))

Bu, herhangi bir sıradaki [(x, y), (x, y), (x, y), (x, y)] içindeki nokta dişlerinin listelerini alır ve kopyaları ya da yanlış noktaları ele alabilir. Diğer python cevapları gibi karmaşık noktalar gerektirmez.

Bu şekilde test edebilirsiniz:

S1 = [(0,0),(1,0),(1,1),(0,1)]   # standard square
S2 = [(0,0),(2,1),(3,-1),(1,-2)] # non-axis-aligned square
S3 = [(0,0),(1,1),(0,1),(1,0)]   # different order
S4 = [(0,0),(2,2),(0,2),(2,0)]   #
S5 = [(0,0),(2,2),(0,2),(2,0),(0,0)] #Redundant points

B1 = [(0,0),(0,2),(3,2),(3,0)]  # rectangle
B2 = [(0,0),(3,4),(8,4),(5,0)]  # rhombus
B3 = [(0,0),(0,0),(1,1),(0,0)]  # only 2 distinct points
B4 = [(0,0),(0,0),(1,0),(0,1)]  # only 3 distinct points
B5 = [(1,1),(2,2),(3,3),(4,4)]  # Points on the same line
B6 = [(0,0),(2,2),(0,2)]        # Not enough points

def tests(f):
    assert(f(S1) == True)
    assert(f(S2) == True)
    assert(f(S3) == True)
    assert(f(S4) == True)
    assert(f(S5) == True)

    assert(f(B1) == False)
    assert(f(B2) == False)
    assert(f(B3) == False)
    assert(f(B4) == False)
    assert(f(B5) == False)
    assert(f(B6) == False)

def t(p):return len(set(p))-1==len(set([pow(pow(a-c,2)+pow(b-d,2),.5)for a,b in p for c,d in p]))

tests(t)

Bu biraz açıklama gerektirecektir, ancak genel fikir, bir kare içindeki noktalar arasında yalnızca üç mesafe olduğu yönündedir (Side, Diagonal, Zero (kendisiyle karşılaştırıldığında puan)):

def t(p):return len(set(p))-1==len(set([pow(pow(a-c,2)+pow(b-d,2),.5)for a,b in p for c,d in p]))
  • t plerin bir listesi için (x, y)
  • Set (p) kullanarak kopyaları kaldırın ve sonra uzunluğu test edin
  • Her nokta kombinasyonunu elde edin (a, b için p, c, d, p)
  • Her noktadan diğer noktalara kadar olan mesafelerin listesini alın
  • Sadece üç benzersiz uzaklık olduğunu kontrol etmek için set kullanın - Sıfır (kendisiyle karşılaştırıldığında puan) - Yan uzunluk - Çapraz uzunluk

Kod karakterlerini kaydetmek için Ben:

  • 1 karakter işlev ismi kullanarak
  • 1 satır işlev tanımı kullanarak
  • Eşsiz puanların sayısını 4 kontrol etmek yerine, farklı puan uzunluklarının -1 olduğunu kontrol ediyorum (tasarruf == 3 ==)
  • a [b], yerine [1] yerine a, b in p, c in d elde etmek için listeyi ve dizini açma işlemini kullanın.
  • sqrt (x) almak için matematik dahil etmek yerine pow (x, .5) kullanır
  • sonra boşluk bırakmamak
  • şamandıranın önüne sıfır koymamak

Birisinin bunu kıran bir test davası bulabilmesinden korkuyorum. Öyleyse lütfen yap ve düzeltir. Örneğin, bir abs () yapmak ve yan uzunluk ve hipotenüs kontrolü yapmak yerine sadece üç mesafeyi kontrol etmem aslında bir hata gibi görünüyor.

İlk defa golf kodunu denedim. Ev kurallarına uymazsam kibar olun.


1

Clojure, 159 karakter.

user=> (def squares
         [[[0,0] [0,1] [1,1]  [1,0]]   ; standard square
         [[0,0] [2,1] [3,-1] [1,-2]]  ; non-axis-aligned square
         [[0,0] [1,1] [0,1]  [1,0]]]) ; different order
#'user/squares
user=> (def non-squares
         [[[0,0] [0,2] [3,2] [3,0]]    ; rectangle
          [[0,0] [3,4] [8,4] [5,0]]])  ; rhombus
#'user/non-squares
user=> (defn norm
         [x y]
         (reduce + (map (comp #(* % %) -) x y)))
#'user/norm
user=> (defn square?
         [[a b c d]]
         (let [[x y z] (sort (map #(norm a %) [b c d]))]
           (and (= x y) (= z (* 2 x)))))
#'user/square?
user=> (every? square? squares)
true
user=> (not-any? square? non-squares)
true

Düzenleme: Biraz da açıklamak için.

  • İlk önce, verilen iki nokta arasındaki mesafeyi temelde veren bir norm tanımlayın.
  • Sonra ilk noktanın diğer üç noktaya olan mesafesini hesaplayın.
  • Üç mesafeyi sıralayın. (Bu, herhangi bir puan sırasına izin verir.)
  • En kısa iki mesafe kare şeklinde olmalıdır.
  • Üçüncü (en uzun) uzaklık, Pisagor teoremi tarafından kısa mesafelerin karelerinin toplamının kareköküne eşit olmalıdır.

(Not: kareköklendirme gerekli değildir ve bu nedenle yukarıda kaydedilen kodda.)


1

C #, 107 karakter

return p.Distinct().Count()==4&&
(from a in p from b in p select (a-b).LengthSquared).Distinct().Count()==3;

Noktaları içeren Vector3D listesi.

Tüm noktalar arasında karelenmiş tüm mesafeleri hesaplar ve eğer tam olarak üç ayrı tip varsa (0, bir değer a ve 2 * a olmalıdır) ve 4 ayrı nokta varsa, o zaman noktalar bir kare oluşturur.



1

Python 2,49 bayt

lambda l:all(1j*z+(1-1j)*sum(l)/4in l for z in l)

Çevrimiçi deneyin!

Giriş olarak dört karmaşık sayının listesini alır. Her noktayı ortalamanın 90 derece çevresinde döndürür ve sonuçta ortaya çıkan her noktanın orijinal listede olup olmadığını kontrol eder.

Aynı uzunluk (Python 3 kullanarak daha kısa olsa da {*l}).

lambda l:{1j*z+(1-1j)*sum(l)/4for z in l}==set(l)

Çevrimiçi deneyin!


Kısacası neden Python 3 kullanmıyorsunuz? Ayrıca, Python'da rasgele truthy / falsy değerleri döndürülmesine izin veriliyorsa, ^bunun yerine kullanılabilir ==.
Joel

@Joel Python 2 çoğunlukla tercih edilir ve bunun Python 2'nin Python golf oynadığı düşünüldüğünde 2011'den beri çok eski bir mücadele olduğu söylenebilir. Ve meydan okuma doğru ya da yanlış dönüş diyor, bu yüzden buna şaşırdım. Bu bugün yayınlandıysa, muhtemelen truthy / falsey çıktısını veya iki farklı değerden birini belirtecekti ve bunu varsayılan olarak kabul etmek bile doğru olabilir.
xnor

1

Wolfram Dili (Mathematica) , 32 31 bayt

Tr[#^2]==Tr[#^3]==0&[#-Mean@#]&

Çevrimiçi deneyin!

Karmaşık sayılarla gösterilen noktaların bir listesini alır, ikinci ve üçüncü merkezi momenti hesaplar ve her ikisinin de sıfır olduğunu kontrol eder.

Un-golfed:

S[p_] := Total[(p - Mean[p])^2] == Total[(p - Mean[p])^3] == 0

veya

S[p_] := CentralMoment[p, 2] == CentralMoment[p, 3] == 0

kanıt

Bu kriter yalnızca Gauss tamsayıları değil tüm karmaşık düzlemde çalışır .

  1. Öncelikle, noktaların birlikte çevrilmesi durumunda merkezi anların değişmediğini not ediyoruz . Bir dizi nokta için

    P = Table[c + x[i] + I*y[i], {i, 4}]
    

    merkezi anların hepsi bağımsızdır c(bu yüzden merkez olarak adlandırılırlar ):

    {FreeQ[FullSimplify[CentralMoment[P, 2]], c], FreeQ[FullSimplify[CentralMoment[P, 3]], c]}
    (*    {True, True}    *)
    
  2. İkinci olarak, merkezi anlar, nokta kümesinin genel karmaşık ölçeklendirmesine (ölçekleme ve döndürme) basit bir bağımlılığa sahiptir:

    P = Table[f * (x[i] + I*y[i]), {i, 4}];
    FullSimplify[CentralMoment[P, 2]]
    (*    f^2 * (...)    *)
    FullSimplify[CentralMoment[P, 3]]
    (*    f^3 * (...)    *)
    

    Bu, eğer merkezi bir an sıfır ise, o zaman nokta kümesinin ölçeklendirilmesi ve / veya döndürülmesi, merkezi momenti sıfıra eşit tutacaktır.

  3. Üçüncüsü, ilk iki noktanın sabit olduğu noktaların bir listesini belirleyelim:

    P = {0, 1, x[3] + I*y[3], x[4] + I*y[4]};
    

    İkinci ve üçüncü merkezi anların gerçek ve hayali bölümleri hangi koşullar altında sıfırdır?

    C2 = CentralMoment[P, 2] // ReIm // ComplexExpand // FullSimplify;
    C3 = CentralMoment[P, 3] // ReIm // ComplexExpand // FullSimplify;
    Solve[Thread[Join[C2, C3] == 0], {x[3], y[3], x[4], y[4]}, Reals] // FullSimplify
    (*    {{x[3] -> 0, y[3] -> -1, x[4] -> 1, y[4] -> -1},
           {x[3] -> 0, y[3] -> 1, x[4] -> 1, y[4] -> 1},
           {x[3] -> 1/2, y[3] -> -1/2, x[4] -> 1/2, y[4] -> 1/2},
           {x[3] -> 1/2, y[3] -> 1/2, x[4] -> 1/2, y[4] -> -1/2},
           {x[3] -> 1, y[3] -> -1, x[4] -> 0, y[4] -> -1},
           {x[3] -> 1, y[3] -> 1, x[4] -> 0, y[4] -> 1}}    *)
    

    Bu altı çözümün tümü kareleri temsil eder: görüntü tanımını buraya girin Bu nedenle, form noktalarının listesinin {0, 1, x[3] + I*y[3], x[4] + I*y[4]}sıfır saniye ve üçüncü merkezi momentlere sahip olmasının tek yolu , dört noktanın bir kare oluşturmasıdır.

Nokta 1 ve 2'de gösterilen çeviri, döndürme ve ölçeklendirme özellikleri nedeniyle, bu ikinci ve üçüncü merkezi anların sıfır olduğu her zaman, bazı çeviri / döndürme / ölçekleme durumunda bir karemiz olduğu anlamına gelir. ∎

genelleme

K n ile bölünemezse, normal bir n-gonun k-merkezi anı sıfır olur. N-gons tespitinde yeterli bir kriter oluşturmak için bu şartların yeteri kadar birleştirilmesi gerekir. N = 4 durumu için k = 2 ve k = 3'teki sıfırları saptamak yeterliydi; Tespit etmek için, örneğin altıgenleri (n = 6) sıfırlar için k = 2,3,4,5'i kontrol etmek gerekebilir. Aşağıdakileri ispat etmedim, ancak herhangi bir normal n-gon tespit edeceğinden şüpheleniyorum:

isregularngon[p_List] :=
  And @@ Table[PossibleZeroQ[CentralMoment[p, k]], {k, 2, Length[p] - 1}]

Kod mücadelesi esasen uzunluk-4 listeleri için uzmanlaşmış bu koddur.


Çözüm oldukça ilginç görünüyor. Neden doğru cevap verdiğini açıklayabilir misiniz?
Joel,

@Joel Bir kanıtı ekledim.
Roman

Çok teşekkürler. Bu güzel çözümün daha sezgisel bir matematiksel açıklaması olabilirdi.
Joel,

@Joel Beni bu çözüme götüren ipliği size verebilirim. Karelerin (koordinat listesi olarak, karmaşık sayıların değil) birim matrisle orantılı bir kovaryans matrisine sahip olduğunu fark ederek başladım ; Ancak, bu durum yeterli değil (yanlış pozitif). Herhangi bir nokta simetrisi yapısı için üçüncü merkezi moment sıfır olmalıdır. Böylece ikinci ve üçüncü merkezi anlara bir koşul koymak için karmaşık temsillere geçtim ve şaşırdım ki, ikinci merkezi anın kareler için sıfır olduğu ortaya çıktı.
Roman

Harika. Bu çözüme giden yolu gösterdiğiniz için teşekkür ederiz.
Joel,

0

J, 31 29 27 26

3=[:#[:~.[:,([:+/*:@-)"1/~

Noktalar arasındaki en küçük 8 mesafenin aynı olup olmadığını kontrol eder. Noktalar arasında tam olarak üç çeşit mesafe olup olmadığını kontrol eder (sıfır, yan uzunluk ve çapraz uzunluk).

f 4 2 $ 0 0 2 1 3 _1 1 _2
1
f 4 2 $ 0 0 0 2 3 2 3 0
0

4 2 $ J'de bir dizi yazmanın bir yoludur


Bu eşkenar dörtgen testi başarısız olur.
JB

@JB: Bir yazım hatası vardı. Ben yine de yöntemi değiştirdim.
Eelvex

Eeew ... çaldığım aynı yöntemi kullanıyorsun. Versiyonumun kısa olması dışında: p
JB

@JB: gerçekten mi? Bunu farketmedim. Başka kim kontrol ediyor (3 == #distances)?
Eelvex

@JB: oic ... bazı kombinasyonlar için 2.: - /
Eelvex

0

106 karakter için küçük konuşma

s:=Set new.
p permutationsDo:[:e|s add:((e first - e second) dotProduct:(e first - e third))].
s size = 2

p, bir noktalar topluluğudur, örneğin

p := { 0@0. 2@1. 3@ -1. 1@ -2}. "twisted square"

Bence matematiğin sesi ...


2 farklı nokta ürününü kontrol etmek onu kesmiyor. Aynı pozisyonda yerleştirilen puanlar yanlış pozitifler üretebilir.
aaaaaaaaaaaa 11:11

0

Mathematica, 123 karakter (ancak daha iyisini yapabilirsiniz):

Flatten[Table[x-y,{x,a},{y,a}],1]
Sort[DeleteDuplicates[Abs[Flatten[Table[c.d,{c,%},{d,%}]]]]]
%[[1]]==0&&%[[3]]/%[[2]]==2

'A', Mathematica liste formundaki girdi, örneğin: a={{0,0},{3,4},{8,4},{5,0}}

Anahtar, tüm vektörler arasındaki nokta ürünlerine bakmak ve tam olarak üç değere sahip olmaları gerektiğine dikkat etmektir: x'in bir değeri için 0, x ve 2 * x. Nokta ürün her iki dikliği ve uzunluğu tek bir sopada kontrol eder.

Bunu daha da kısaltabilecek Mathematica kısayolları olduğunu biliyorum, ama ne olduklarını bilmiyorum.


Bunun da yanlış olduğunu düşünüyorum, ancak kodun ne yaptığını çözemiyorum.
aaaaaaaaaaaa 11:11

4 nokta arasındaki tüm vektörleri hesaplar, tüm nokta ürünlerini alır (mutlak değer) ve sonucun, x'in bir değeri için tam olarak 0, x, 2 * x'ten oluşmasını bekler.
barrycarter

Öyleyse 16 vektör -> 256 nokta ürün ve yüksek değerin 2 kat düşük olduğunu kontrol edersiniz, ancak her bir değerin kaç tane olduğunu bilmiyorsunuz. Doğru anlaşıldı mı?
aaaaaaaaaaaa 11:11

Evet, bu algoritmamı doğru bir şekilde tarif ediyor. Ve şimdi haklı olduğunuzu düşünüyorum: 3 değerin de gerçekleştiği, ancak doğru miktarda olmadığı bir senaryo oluşturabilirsiniz. Sıçanlar. Yine de tamir edilebilir mi olmalı?
barrycarter

@barrycarter Sen kullanarak karakterleri kaydedebilirsiniz Unionyerine Sort@DeleteDuplicates. Ayrıca 3 satırınızı da bir araya getirdim:#[[1]] == 0 && #[[3]]/#[[2]] == 2 &[ Union@Abs@Flatten[Table[c.d, {c, #}, {d, #}]] &[ Flatten[Table[x - y, {x, a}, {y, a}], 1]]]
DavidC

0

Haskell, "wc -c", 110 karakter bildirir. Girişin 4 elementi olduğunu kontrol etmez.

import Data.List
k [a,b]=2*a==b
k _=0<1
h ((a,b):t)=map (\(c,d)->(a-c)^2+(b-d)^2) t++h t
h _=[]
j=k.nub.sort.h

Üzerinde test ettim

test1 = [(0,0),(3,4),(-4,3),(-1,7)] -- j test1 is True
test2 = [(0,0),(3,4),(-3,4),(0,8)]  -- j test2 is False

Yukarıdakilerin hiçbir zaman bir noktadan kendisine kadar olan mesafeyi alamayacağına dikkat edin, bu nedenle 0 mesafesinin varlığı giriş listesinde tekrarlanan bir noktaya işaret eder ve bu da sıralama listesinde k [0, b] ve 2 * olarak gösterilir. 0 == b her zaman başarısız olur çünkü b 0 ile aynı olamaz
Chris Kuklewicz
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.