确定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,我当时以为这意味着这些点在一个平面上,但是由于某种原因,我在3D空间中看到了一个平面:)
1
@eBusiness:-1表示您投了11票:其中7票被拒绝。
Answers:
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)。如果我们知道一个正方形的中心和一个角,则可以通过围绕中心点(c)旋转90,180和270度的角来重建正方形。在复平面上,通过将点乘以i可以绕原点旋转90度。如果我们的原始形状和重建的正方形具有相同的点,那么它一定是正方形。
一些优化:1)使用“ S”代替“ is_square” 2)使用;将其全部放在一行上;3)直接在4个方向上迭代“ for i in(1,1j,-1,-1j)” 4)在set参数中不需要[]。
谢谢基思。(我忽略了(3),因为它看起来与我的代码长度相同)
—
纸
2
@Keith Randall-为什么当JB的解决方案要短得多时,这被接受了?
1
有两个原因。第一,J总是赢。所以我喜欢按语言归一化。另外,我更喜欢这个答案,因为它不会像其他答案(当然,只有非理性的答案)给出错误肯定的情况那样,受到与仅基于距离的答案相同的困扰。
5
@Keith Randall-问题引号:“这些点将具有整数坐标”“最短的代码获胜。”。如果您选择不同的条件来选择答案,甚至是主观条件,那也很好,但是您应该在问题中说明。
13
J,28 17 25 27
J并没有真正的功能,但是这是一个单调动词,它从复杂平面中获取点向量:
4 8 4-:#/.~&(/:~&:|&,&(-/~))
方法是将迈克尔·斯宾塞(Michael Spencer)(仅在顶点间的长度上工作;但他目前无法使我的菱形2)和Eelvex(检查布景的大小)混合使用。从右到左阅读:
-/~ 计算所有点差
, 展平
| 提取幅度
/:~ 整理
#/.~ 算数
4 8 4 -:必须正好有4个等距距离(在0处),8个等距点(长度1,边),4个等距点(length 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
喔好吧。我当时正在考虑以第四个点为中心的等边三角形,但是这被整数坐标所排除
1
您可以通过将其更改为显式定义来削减3个字符: 3 :'4 8 4-:#/.~/:~|,-/~y'
5
蟒蛇,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)为每个规范定义一个函数
对于正方形,任意两点之间的向量必须为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)
我认为该问题明确指出了要点列表,而不是向量。
1
那么(0 + 0j,0 + 0j,1 + 0j,0 + 1j)是一个正方形吗?
我的菱形2不是1 +/- 60j,它更像exp(i j pi / 3)的值是-1、0、1。请注意,正如eBusiness指出的那样,它们不可能全部都是整数,所以并不是真的问题的范围。
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
您可以删除多余的空间并重命名一些内容,将其刮到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
让我们使用QuickCheck来确保它接受任意正方形,其中一个顶点位于(x,y),边缘矢量(a,b):
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个字符d。s l=[4,8,4]==(map length.group.sort)[(x-a)^2+(y-b)^2|(x,y)
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,145164
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
编辑:遵循了乔凡尼尼的建议。
真好 我们在这里没有看到太多的OCaml :)
使用运算符代替,n以减少20个字符: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点之间成对(非零)距离的列表。在两个唯一的组中,总共应该有12个距离。
def f(p):s = filter(None,[[(xz)** 2+(yw)** 2对于x,y在p中用于z,w在p中]]);返回len(s)== 12and len(集)== 2
您可以省略过滤器,并检查集合的len是否为3。这也遭受了与我的回答相同的误报问题。
>>> F([(0,0),(0,4),(2,2),( - 2,2)])= TRUE
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。在输入中选择不同的点的两个组合,计算它们的距离,然后验证它们中的四个正好相等,并且仅存在另一个不同的距离值。Point是具有两个双重成员X和Y的类。很容易成为Tuple,但是。
var points = new List
{
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(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); 图不是。
2
K -33
{4 8 4~#:'=_sqrt+/'_sqr,/x-/:\:x}
K在这里受其保留字(_sqr和_sqrt)的影响。
测试:
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 +电池,132个字符
let q l=match List.group(-)[?List:(x-z)*(x-z)+(y-t)*(y-t)|x,y2*s=d|_->false
(看,Ma,没有空格!)列表理解以q表格形式列出了每个不同的无序点对的平方范数。一个正方形具有四个相等的边和两个相等的对角线,后者的平方长度是前者的平方长度的两倍。由于整数晶格中没有等边三角形,因此该测试并不是真正必要的,但出于完整性考虑,我将其包括在内。
测试:
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,并且两者中的较短者不为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
False
注意:\[And]是Mathematica中的单个字符。
1
您是在告诉我Mathematica没有内置的IsSquare函数吗?
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
天真的第一次尝试。检查点输入列表的所有排列的以下两个条件(给定排列表示点的顺时针排序):
所有角度均为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])+"
")
}
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,161158个字符
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];}
从问题陈述中还不清楚点是按顺序排列的。我去问问。
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功能(表达式闭包,数组理解,解构分配)。还滥用~~(双位非运算符)强制转换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)]]
输出true为true,空白为false
@Jonas:我还没有看到任何真正正式的东西,我看到的最好的博客文章就是这一篇。实际上,我实际上无法使它构建和工作,但另一种方法是将golf-prelude复制到相同的文件夹中并运行ruby -r ./golf-prelude.rb FILE_TO_RUN.rb,并且工作原理完全相同。
sort之前没有必要group_by。.sort.group_by {...}应该写为.group_by {...}
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)
这将需要一些解释,但是总体思路是,正方形中的点(侧面,对角线,零(点与自身相比,点))之间只有三个距离:
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中的a,b代表c,d中的d)
获取每个点到每个其他点的距离列表
使用设置检查只有三个唯一的距离-零(与自身相比的点)-边长-对角线长度
要保存代码字符,我是:
使用1个char函数名称
使用1行函数定义
不用检查唯一点的数量是4,而是检查不同点的长度是-1(节省== 3 ==)
使用列表和元组解包获得p中的a,b以获得p中的c,d,而不是使用a [0],a [1]
使用pow(x,.5)而不是包括数学来获取sqrt(x)
不在)后放置空格
不要将浮动的前导零
我担心有人会找到打破这一点的测试案例。因此,请这样做,不适。例如,我只检查三个距离而不是进行abs()并检查边长和斜边的事实,似乎是一个错误。
第一次我尝试编码高尔夫。如果我违反任何家庭规矩,请保持友善。
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
编辑:也要解释一下。
首先定义一个规范,该规范基本上给出两个给定点之间的距离。
然后计算第一个点到其他三个点的距离。
对三个距离进行排序。(这允许点的任何顺序。)
两个最短距离必须等于一个正方形。
根据毕达哥拉斯定理,第三(最长)距离必须等于短距离平方和的平方根。
(注意:不需要平方根,因此在上面保存的代码中。)
1
C#,107个字符
return p.Distinct().Count()==4&&
(from a in p from b in p select (a-b).LengthSquared).Distinct().Count()==3;
点是包含点的Vector3D列表。
计算所有点之间的所有距离的平方,如果恰好存在三种不同的类型(必须为0,某个值a和2 * a)和4个不同的点,则这些点将形成一个正方形。
1
Python,66岁
将纸马的答案从76 提高到66:
def U(A):c=sum(A)/4;d=A[0]-c;return{d+c,c-d,d*1j+c,c-d*1j}==set(A)
1
Python 2,49个字节
lambdal:all(1j*z+(1-1j)*sum(l)/4inlforzinl)
将四个复数的列表作为输入。将每个点围绕平均值旋转90度,并检查每个结果点是否在原始列表中。
相同的长度(尽管在Python 3中使用较短{*l})。
lambdal:{1j*z+(1-1j)*sum(l)/4forzinl}==set(l)
如果那更短,为什么不使用Python 3?另外,如果允许在Python中返回任意的true / falsy值,^则可以使用代替==。
@Joel Python 2在大多数情况下是首选,这是2011年以来的一个非常古老的挑战,当时Python 2几乎被认为是Python高尔夫。挑战是返回真还是假,所以我坚持了这一点。如果今天发布此消息,则可能会指定输出true / falsey或两个不同值之一,甚至可以通过OK假定默认情况下。
1
Tr[#^2]==Tr[#^3]==0&[#-Mean@#]&
取得由复数表示的点的列表,计算第二和第三中心矩,并检查它们是否均为零。
未打高尔夫球:
S[p_] := Total[(p - Mean[p])^2] == Total[(p - Mean[p])^3] == 0
要么
S[p_] := CentralMoment[p, 2] == CentralMoment[p, 3] == 0
证明
此准则适用于整个复平面,而不仅适用于高斯整数。
首先,我们注意到当点一起平移时,中心矩不会改变。对于一组要点
P = Table[c + x[i] + I*y[i], {i, 4}]
中心矩都独立于c(这就是为什么它们被称为Central):
{FreeQ[FullSimplify[CentralMoment[P, 2]], c], FreeQ[FullSimplify[CentralMoment[P, 3]], c]}
(* {True, True} *)
其次,中心矩简单地依赖于一组点的整体复杂缩放(缩放和旋转):
P = Table[f * (x[i] + I*y[i]), {i, 4}];
FullSimplify[CentralMoment[P, 2]]
(* f^2 * (...) *)
FullSimplify[CentralMoment[P, 3]]
(* f^3 * (...) *)
这意味着,如果中心矩为零,则缩放和/或旋转点集将使中心矩等于零。
第三,让我们证明前两个点固定的点列表的标准:
P = {0, 1, x[3] + I*y[3], x[4] + I*y[4]};
在什么条件下,第二和第三中心矩的实部和虚部为零?
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}} *)
所有这六个解都表示一个正方形:
因此,形式的点列表{0, 1, x[3] + I*y[3], x[4] + I*y[4]}可以具有零个第二和第三中心矩的唯一方法是当四个点形成一个正方形时。
由于点1和点2所示的平移,旋转和缩放属性,这意味着在第二和第三中心矩为零的任何时候,我们在某个平移/旋转/缩放状态下都有一个正方形。∎
概括
如果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我添加了一个证明。
非常感谢。理想的情况是对该解决方案进行更直观的数学解释。
@Joel我可以给您提供导致我找到此解决方案的线索。首先,我注意到正方形(作为坐标列表,而不是复数)具有与单位矩阵成比例的协方差矩阵。但是,此条件还不够(误报)。对于任何点对称结构,第三中心矩必须为零。因此,我转而使用复数表示法在第二和第三中心矩上设置了条件,令我惊讶的是,事实证明第二中心矩对于正方形为零。
大。感谢您显示此解决方案的路径。
0
J,31 29 27 26
3=[:#[:~.[:,([:+/*:@-)"1/~
检查点之间的8个最小距离是否相同。
检查点之间是否存在三种距离(零,边长和对角线长度)。
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:我有错字。我现在还是改变了方法。
哎呀...您使用的是我偷走的相同方法。除了我的版本更短:p
@JB:真的吗?我没注意到。还有谁检查(3 == #distances)?
@JB:oic ...对2的组合进行一些检查:://
0
Smalltalk为106个字符
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个不同的点产品不会减少它。放置在相同位置的点可能会产生误报。
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。点积会检查一个膨胀管的垂直度和长度。
我知道有一些Mathematica快捷方式可以使它更短,但我不知道它们是什么。
我认为这也是错误的,但是我无法弄清楚代码的作用。
它计算4个点之间的所有向量,取所有点积(绝对值),并期望结果对于x的某个值正好由0,x,2 * x组成。
因此,有16个向量-> 256个点积,您要检查高值是低值的2倍,但您不必知道每个值有多少。是正确的理解吗?
是的,正确描述了我的算法。我现在认为您是对的:您可以构建一个场景,其中所有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]]]
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 * 0 == b就总是失败,因为b不能是相同的为0