4点が正方形を形成するかどうかを判別


29

入力として平面上の4点を取り、4点が正方形を形成する場合にtrueを返す関数を記述します。ポイントには、絶対値<1000の整数座標があります。

入力として4つのポイントの合理的な表現を使用できます。ポイントは特定の順序で提供されません。

最短のコードが優先されます。

正方形の例:

(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,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

縮退した正方形に対してtrueまたはfalseを返すことができます (0,0),(0,0),(0,0),(0,0)


ここで3Dポイントについて話しますよね?
ニブラー

3
@gnibbler「に関する質問メイク3Dの飛行機」の部分はそう指摘します。
JB

ポイントは順番に与えられていますか?
JB

@JB、ポイントが平面上にあることを意味していると考えていましたが、何らかの理由で3D空間で平面を視覚化しました:)
ニブラー

1
@eBusiness:11票を投じた-1:7票が下がっています。
エルベックス

回答:


12

Python 176 90 79バイト

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

関数Sは、入力(A)として複素数のリストを受け取ります。正方形の中心と1つの角の両方がわかっている場合、中心点を中心に90、180、270度の角を回転させることで正方形を再構成できます(c)。複素平面上で、原点を中心とした90度の回転は、ポイントにiを掛けることによって行われます。元の形状と再構成された正方形のポイントが同じ場合、正方形である必要があります。


いくつかの最適化:1) "is_square"の代わりに "S"を使用します2);を使用してすべてを1行に配置します 3)「for i in(1,1j、-1、-1j)」の4つの方向を直接反復します4)set引数で[]を必要としません。
キースランドール

ありがとうキース。(コードと同じ長さのように見えるため、(3)を
省略しました

2
@Keith Randall-JBのソリューションがはるかに短い場合、なぜこれが受け入れられたのですか?
aaaaaaaaaaaa

1
2つの理由。1つは、Jが常に勝つことです。だから私は言語で少し正規化するのが好きです。また、他の数字(確かに、非合理的な数字のみ)が偽陽性を与える距離のみの回答と同じ問題に悩まされないため、この回答がより気に入っています。
キースランドール

5
@Keith Randall-質問からの引用:「ポイントには整数座標があります」「最短コードが勝ちます。」。回答を選択するためのさまざまな基準、主観的な基準を選択してもまったく問題ありませんが、それを質問に記載する必要があります。
aaaaaaaaaaaa

13

J、28 17 25 27

Jには実際には関数はありませんが、複素平面から点のベクトルを取得する単項動詞は次のとおりです。

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

メソッドは、マイケルスペンサー(頂点間の長さのみで動作しますが、現在彼は私のrhombus2に失敗しています)とEelvexの動作(セットのサイズを確認)が混在しています。右から左に読む:

  • -/~ すべての点差を計算する
  • , 平らにする
  • | 大きさを抽出する
  • /:~ 整理する
  • #/.~ ナブとカウント
  • 4 8 4 -:正確に4つの等距離(0で)、8が少し大きく(長さ1、両側)、さらに4つが大きく(長さsqrt 2、対角線)

デモンストレーション:

   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

メモリのために、以前の方法(順序付けられた頂点が必要でしたが、任意の順序の通常のポリゴンを検​​出できました):

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

説明とデモについては履歴を参照してください。現在の方法は、おそらく他のポリゴンに拡張できますが、これ4 8 4は二項分布によく似ています。


この言語にリンクできますか?
サーガンディロン

1
@gnibbler:どうしてですか?確かにそうです。
エルベックス

1
実際には、チェックする条件を満たす非正方形の図が存在します。正三角形と、延長された中央値に配置された三角形の先端からの辺の長さの1点です。しかし、質問は整数入力を要求したので、解決策は大丈夫だと思います。
aaaaaaaaaaaa

1
ああ、わかった。私は4番目の点を中心とする正三角形を考えていましたが、整数座標によって除外されます
ニブラー

1
明示的な定義に変更することで3文字をカットできます 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

更新1)4つの異なるポイントを要求する(以前は繰り返しポイントに対して誤検知を与えていましたが、他にもありますか?)2)仕様ごとに関数を定義する

正方形の場合、2点間のベクトルは0(同じ点)、辺、または対角線でなければなりません。したがって、これらのベクトルの大きさのセットの長さは3でなければなりません。

# 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)

この質問は、ベクトルではなく、ポイントのリストを明示的に述べていると思います。
サーガンディロン

偽陽性。
aaaaaaaaaaaa

1
(0 + 0j、0 + 0j、1 + 0j、0 + 1j)は正方形ですか?
mhagger

私の菱形2は1 +/- 60jではなく、-1、0、1の値のexp(i j pi / 3)のようなものです。質問の範囲。
JB

3

Haskell、100文字

HaskellでJBのJソリューションを作成する方法を次に示します。不要な文字を削除して読みやすさを損なうことを試みなかった場合、約132文字になります。

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]

余分なスペースを削除していくつかの名前を変更することで、100に少し削ることができます

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]

QuickCheckを使用して、(x、y)とエッジベクトル(a、b)に1つの頂点がある任意の正方形を受け入れるようにします。

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

ghciで試してください:

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

ああ、空の正方形はここでは正方形とはみなされないので、テストを修正します。

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)]

そしてもう一度試してください:

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

1
関数を展開して11文字保存しますds l=[4,8,4]==(map length.group.sort)[(x-a)^2+(y-b)^2|(x,y)<-l,(a,b)<-l]
レイ

3

因子

Factorプログラミング言語での実装:

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 ;

そしていくつかのユニットテスト:

[ 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

次のように実行します:

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

難読化を解除して、少し説明しましょう。

まず、ノルムを定義します:

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

sqrtの呼び出しがないことに気付くでしょう。ここでは必要ありません。

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

ここで、a、b、c、およびdはポイントです。これらのポイントは次のようにレイアウトされていると仮定します。

a - b
| / |
c - d

正方形がある場合、これらすべての条件が満たされなければなりません:

  • abcは直角三角形です
  • bcdは直角三角形です
  • 各直角三角形の小さい辺は同じ基準を持っています

以下が常に成り立つことに注意してください。

is_square_with_fixed_layout r s t u = is_square_with_fixed_layout r t s u

これを使用して、以下のテスト機能を簡素化します。

入力は順序付けられていないため、すべての順列もチェックする必要があります。一般性を失うことなく、最初の点の順列を避けることができます。

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

簡略化後:

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

編集:M.Giovanniniのアドバイスに従いました。


いいね ここではOCamlをあまり見ていません:)
Eelvex

n20文字削減する代わりに演算子を使用します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
マティアスジョヴァンニ

2

パイソン(105)

ポイントは(x,y)タプルで表されます。ポイントは任意の順序にすることができ、正方形のみを受け入れます。sポイント間のペアワイズ(非ゼロ)距離のリストを作成します。2つの一意のグループで、合計で12の距離が必要です。

def f(p):s = filter(None、[(xz)** 2 + 2 +(yw)** 2 for x、y for p for z、w in p]); return len(s)== 12and len(セット)== 2

フィルターを省いて、セットのlenが3であるかどうかを確認できます。これは、私の答えと同じ誤検知の問題があります。
ニブラー

>>> f([(0,0)、(0,4)、(2,2)、(-2,2)])= True
Sargun Dhillon

2
f([(0,0),(0,4),(2,2),(-2,2)]) は正方形です
ニブラー

2

Python-42文字

ポイントに複素数を使用すると改善されるようです

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

ここで、A = [(11 + 13j)、(14 + 12j)、(13 + 9j)、(10 + 10j)]

古い答え:

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

ポイントはリストとして任意の順序で指定されます。例えば

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、これは機能しない入力クラス全体の特殊なケースです。私は答えの大きさを吹き飛ばさない修正を考えています。一方、失敗したケースの一般的なクラスを解決できますか?
ニブラー

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:その例は正方形です。
キースランドール

重複したポイントを取り除くには、-set([0])を追加できます
キースランドール

2

C#-正確ではありません。LINQの乱用。入力内のポイントの異なる2つの組み合わせを選択し、それらの距離を計算し、正確に4つのポイントが等しいこと、および他の1つの距離値のみがあることを確認します。Pointは、XとYの2つのダブルメンバーを持つクラスです。簡単にタプルになりますが、そうです。

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文字


//$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]))};

しかし、境界ボックスが正方形であるからといって、ポイントが正方形にあるわけではありません。必要だが十分ではない状態。(0,0)、(5,5)、(10,0)、(0、-5)を検討してください。境界ボックスは正方形(0:10、-5:5)です。図ではありません。
フローリス14


2

OCaml +バッテリー、132文字

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

(見て、Ma、スペースなし!)内のリストの理解 q、それぞれの異なる順序付けられていないポイントのペアの二乗ノルムのリストを形成します。正方形には4つの等しい辺と2つの等しい対角線があり、後者の正方形の長さは前者の2倍の長さです。整数格子には正三角形がないため、テストは実際には必要ありませんが、完全を期すためにテストを含めています。

テスト:

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

個別のポイント間距離の数(ポイントからそれ自体までの距離を含まない)が2であり、2つの短い方が0でないことを確認します。

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

使用法

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 *)







False False

NB:\[And]Mathematicaの単一文字です。


1
MathematicaにはIsSquare関数が組み込まれていないと言っていますか?
-goodguy

2

ゼリー、8バイト

_Æm×ıḟƊṆ

オンラインでお試しください!

複素数のリストをコマンドライン引数として受け取ります。印刷1または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.

これは復活する楽しい挑戦のようです!


1

ハスケル(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

素朴な最初の試み。ポイントの入力リストのすべての順列について、次の2つの条件をチェックします(指定された順列は、例えば、ポイントの時計回りの順序を表します)。

  • すべての角度は90度です
  • すべての辺は同じ長さです

難読化解除されたコードとテスト

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

Scala(146文字)

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文字

J Bsの答えと数学的に等しい。6つの長さを生成し、最大の2つが等しく、最小の4つが等しいと断定します。入力は配列の配列でなければなりません。

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文字

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];}

証明(1x1):http : //codepad.viper-7.com/ZlBpOB

これはeBuisnessのJavaScriptの回答に基づいています


問題の声明から、ポイントが順番に並んでいくのは少し不明瞭です。私は尋ねに行きます。
JB

1
これが多くのケースを適切に処理するとは思わない。たとえば、菱形を誤って正方形としてラベル付けします。
キースランドール

JavaScriptの回答のいずれかに一致するようにこれを更新し、すべてのケースを処理する必要があります。
ケビンブラウン

1

JavaScript 1.8、112文字

更新:配列内包表記を折り畳むことで2文字を保存しました。

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の答えの別の再実装。JavaScript 1.7 / 1.8の機能を活用します(式のクロージャー、配列の理解、割り当ての破壊)。また、配列から文字列への強制と長さのカウントが正しいことを確認するための正規表現を使用して、数値~~に強制する不正な(ダブルビット単位のnot演算子)undefined[4, 8, 4]正確に4ポイントが渡されることを前提としています)。コンマ演算子の乱用は、難読化された古いCのトリックです。

テスト:

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文字

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

展開された:

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の答えと同じアルゴリズム

次のようなテスト:

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

truetrueの場合は出力、falseの場合は空白


GoRubyについて聞いたことがない。それについて書かれた公式はありますか?stackoverflow.com/questions/63998/hidden-features-of-ruby/...
ジョナスElfström

@ジョナス:私はそれについて本当に公式なものを見ていません、私が見た最高のブログ投稿はこれです。実際に構築して動作させることはできませんでしたが、代わりにゴルフの前奏曲を同じフォルダーにコピーして実行するだけで、まったく同じruby -r ./golf-prelude.rb FILE_TO_RUN.rbように動作します。
Nemo157

sort前にする必要はありませんgroup_by.sort.group_by {...}ように書かれている必要があります.group_by {...}
user102008

1

Python 97(複雑なポイントなし)

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]))

これは、[(x、y)、(x、y)、(x、y)、(x、y)]のポイントタプルのリストを任意の順序で受け取り、重複または間違った数のポイントを処理できます。他のPythonの回答のような複雑なポイントは必要ありません。

次のようにテストできます。

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)

これには少し説明が必要ですが、全体的な考え方は、正方形のポイント間に3つの距離しかないということです(側面、対角線、ゼロ(それ自体と比較したポイント)):

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]))
  • タプルのリストp(x、y)
  • set(p)を使用して重複を削除し、長さをテストします
  • 点のすべての組み合わせを取得します(pのc、dに対してpのa、b)
  • すべてのポイントから他のすべてのポイントまでの距離のリストを取得する
  • セットを使用して、3つの固有の距離しかないことを確認します-ゼロ(それ自体と比較したポイント)-辺の長さ-対角線の長さ

コード文字を保存するには:

  • 1文字の関数名を使用
  • 1行の関数定義を使用する
  • 一意のポイントの数が4であるかどうかを確認する代わりに、異なるポイントの長さが-1であることを確認します(保存== 3 ==)
  • リストとタプルのアンパックを使用して、a [0]、a [1]を使用する代わりに、pのc、dの代わりにpのa、bを取得します。
  • 数学を含める代わりにpow(x、.5)を使用してsqrt(x)を取得します
  • )の後にスペースを入れない
  • フロートに先行ゼロを置かない

誰かがこれを破るテストケースを見つけることができるのではないかと思う。そうしてください、そして、病気を修正してください。たとえば、abs()を実行して辺の長さと斜辺をチェックするのではなく、3つの距離をチェックするだけのことはエラーのようです。

初めてコードゴルフを試しました。ハウスルールを破ったら親切にしてください。


1

Clojure、159文字。

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

編集:少し説明します。

  • 最初に、2つの与えられたポイント間の距離を基本的に与えるノルムを定義します。
  • 次に、最初のポイントから他の3つのポイントまでの距離を計算します。
  • 3つの距離を並べ替えます。(これにより、ポイントの任意の順序が可能になります。)
  • 2つの最短距離は、正方形になるように等しくなければなりません。
  • 3番目の(最長)距離は、ピタゴラスの定理による短距離の平方和の平方根に等しくなければなりません。

(注:平方根は必要ないため、上記で保存したコードでは。)


1

C#、107文字

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

pointsは、ポイントを含むVector3Dのリストです。

すべてのポイント間で平方されたすべての距離を計算し、正確に3つの異なるタイプ(0、ある値a、2 * aでなければならない)と4つの異なるポイントがある場合、ポイントは正方形を形成します。



1

Python 2、49バイト

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

オンラインでお試しください!

4つの複素数のリストを入力として受け取ります。各ポイントを平均を中心に90度回転し、結果の各ポイントが元のリストにあることを確認します。

同じ長さ(ただし、Python 3ではを使用して短くなります{*l})。

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

オンラインでお試しください!


短い場合はPython 3を使用してください。また、Pythonで任意の真実/偽の値を返すことが許可されている場合は、の^代わりに使用できます==
ジョエル

@Joel Python 2はほとんどが好みであり、これはPython 2がPythonゴルフを前提とする2011年からの非常に古い挑戦であるということです。そして、チャレンジはtrueまたはfalseを返すように指示しているので、私はそれにこだわっています。これが今日投稿された場​​合、それはおそらく真実/偽りまたは2つの異なる値のいずれかを出力することを指定し、デフォルトでそれを仮定することもOKかもしれません。
xnor

1

Wolfram言語(Mathematica)32 31バイト

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

オンラインでお試しください!

複素数で表される点のリストを取得し、2番目と3番目の中心モーメントを計算し、両方がゼロであることを確認します。

ゴルフをしていない:

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

または

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

証明

この基準は、ガウス整数だけでなく、複素平面全体で機能します

  1. まず、ポイントが一緒に変換されても、中心モーメントは変わらないことに注意してください。ポイントのセットについて

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

    中心の瞬間はすべて独立していますc(そのため、中心と呼ばれます)。

    {FreeQ[FullSimplify[CentralMoment[P, 2]], c], FreeQ[FullSimplify[CentralMoment[P, 3]], c]}
    (*    {True, True}    *)
    
  2. 第二に、中心モーメントは、ポイントセットの全体的な複雑なスケーリング(スケーリングと回転)に単純に依存します。

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

    これは、中心モーメントがゼロの場合、ポイントのセットをスケーリングおよび/または回転すると、中心モーメントがゼロに等しくなることを意味します。

  3. 第三に、最初の2つの点が固定されている点のリストの基準を証明しましょう。

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

    どのような条件下で、2番目と3番目の中心モーメントの実数部と虚数部はゼロになりますか?

    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}}    *)
    

    これらの6つのソリューションはすべて正方形を表しています。 ここに画像の説明を入力してください したがって、フォームのポイントのリスト{0, 1, x[3] + I*y[3], x[4] + I*y[4]}がゼロの2番目と3番目の中心モーメントを持つ唯一の方法は、4つのポイントが正方形を形成するときです。

ポイント1と2で示されている平行移動、回転、スケーリングの特性により、2番目と3番目の中心モーメントがゼロのときは常に、平行移動/回転/スケーリング状態の正方形が存在することを意味します。∎

一般化

kがnで割り切れない場合、通常のn角形のk番目の中心モーメントはゼロです。これらの条件を十分に組み合わせて、nゴンを検出するための十分な基準を作成する必要があります。n = 4の場合、k = 2およびk = 3のゼロを検出するだけで十分です。たとえば、六角形(n = 6)を検出するには、ゼロのk = 2,3,4,5を確認する必要があります。次のことは証明していませんが、通常のn-gonを検出すると思われます。

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

コードの課題は、基本的に長さ4のリストに特化したこのコードです。


ソリューションはかなり興味深いようです。それが正しい答えを与える理由を説明してもらえますか?
ジョエル

@Joel証拠を追加しました。
ローマ

どうもありがとう。この優れたソリューションについて、より直感的な数学的説明があれば理想的です。
ジョエル

@ジョエル私はこのソリューションに私を導いたスレッドを与えることができます。正方形(複素数ではなく、座標のリスト)には単位行列に比例する共分散行列があることに気づきました。ただし、この条件は十分ではありません(誤検知)。点対称の構造では、3番目の中心モーメントはゼロでなければなりません。そこで、2番目と3番目の中心モーメントに条件を設定するために複雑な表現に切り替えましたが、驚いたことに、2番目の中心モーメントは正方形ではゼロであることがわかりました。
ローマ

すばらしいです。このソリューションへの道を示してくれてありがとう。
ジョエル

0

J、31 29 27 26

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

ポイント間の8つの最小距離が同じかどうかを確認します。 点間に正確に3種類の距離(ゼロ、辺の長さ、対角線の長さ)があるかどうかをチェックします。

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で配列を記述する方法です。


これは菱形テストに失敗します。
JB

@JB:タイプミスがありました。とにかくメソッドを変更しました。
エルベックス

ええ...あなたは私が盗んだのと同じ方法を取っています。私のバージョンの短いを除いて:p
JB

@JB:本当ですか?私はそれに気づかなかった。他に誰がチェックしますか(3 ==#距離)?
エルベックス

@JB:oic ... 2の組み合わせのチェック:-/
Eelvex

0

106文字のSmalltalk

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

ここで、pはポイントのコレクションです。たとえば

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

私は数学が健全だと思う...


2つの異なるドット積をチェックしても、カットされません。同じ位置に配置されたポイントは、誤検知を引き起こす可能性があります。
aaaaaaaaaaaa

0

Mathematica、123文字(ただし、もっとうまくできます):

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リスト形式の入力です。例: a={{0,0},{3,4},{8,4},{5,0}}

キーは、ドットを見て、すべてのベクトル間積、xの値に対して0、x、および2 * xの3つの値を正確に持たなければならないことに注意することです。内積は、1つのうねりで垂直性と長さの両方をチェックします。

これを短くできるMathematicaショートカットがあることは知っていますが、それが何であるかはわかりません。


これも間違っていると思いますが、コードが何をするのかわかりません。
aaaaaaaaaaaa

4つのポイント間のすべてのベクトルを計算し、すべての内積(絶対値)を取得し、xの値に対して結果が正確に0、x、2 * xで構成されると予測します。
バリーカーター

したがって、16個のベクトル-> 256ドット積で、高値が低値の2倍であることを確認しますが、各値の数は確認しません。正しいことを理解していますか?
aaaaaaaaaaaa

はい、それは私のアルゴリズムを正しく説明しています。そして今、私はあなたが正しいと思います:3つの値すべてが発生したが、適切な量ではないシナリオを構築できます。ラット。ただし、修正可能にする必要がありますか?
バリーカーター

@barrycarterのUnion代わりにを使用して文字を保存できますSort@DeleteDuplicates。私もあなたの3行をまとめます#[[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文字を報告します。入力に4つの要素があることを確認しません。

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

私がテストしました

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

上記はポイントからそれ自体までの距離を取得しないため、0の距離の存在は入力リスト内の繰り返されたポイントを示し、これはソートされたリストにk [0、b]として表示されるため、2 * bは0と同じにすることはできませんので、0 == bが常に失敗する
クリスKuklewicz
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.