
is_square?
By:
ploffie on
Jan 2nd, 2013 | syntax:
Python | size: 2.46 KB | hits: 35 | expires: Never
from itertools import combinations
def distsq(p1, p2):
x1, y1 = p1
x2, y2 = p2
return (x2 - x1) ** 2 + (y2 - y1) ** 2
def is_square(p1, p2, p3, p4):
# check for double points first
if any(a == b for a, b in combinations((p1, p2, p3, p4), 2)):
return False
dis = [distsq(p1, p) for p in (p2, p3, p4)]
pmin = min(dis)
pmax = max(dis)
if not (pmax == 2 * pmin and dis.count(pmin) == 2):
return False
# find point furthest away and assert that distances of that point to the 2
# remaining points are the same as pmin
far_pt = (p2, p3, p4)[dis.index(pmax)]
return all(distsq(far_pt, p) == pmin for p in (p2, p3, p4) if p != far_pt)
if __name__ == "__main__":
"""random test against brute force function (is_square0)"""
import random
ran = random.randint
X = 5
def sub(a, b):
return (a[0] - b[0], a[1] - b[1])
def add(a, b):
return (a[0] + b[0], a[1] + b[1])
def is_square0(p1, p2, p3, p4):
"""for testing - check everything to death"""
if any(a == b for a, b in combinations((p1,p2,p3,p4), 2)):
return False
dis = [distsq(p1, p) for p in (p2,p3,p4)]
pmin = min(dis)
pmax = max(dis)
if not (pmax == (2 * pmin) and dis.count(pmin) == 2):
return False
dis = [distsq(p2, p) for p in (p1, p3,p4)]
if not (pmin == min(dis) and pmax == max(dis)):
return False
dis = [distsq(p3, p) for p in (p1, p2,p4)]
if not (pmin == min(dis) and pmax == max(dis)):
return False
dis = [distsq(p4, p) for p in (p1, p3,p2)]
if not (pmin == min(dis) and pmax == max(dis)):
return False
return True
def rect():
b = a = (ran(-X, X), ran(-X, X))
while a == b:
b = (ran(-X, X), ran(-X, X))
dx,dy = sub(b, a)
c = add(a, (dy, -dx))
d = add(b, (dy, -dx))
return a, b, c, d
def norect():
"""random - still could be rect"""
return [(ran(-X, X), ran(-X, X)) for i in range(4)]
for i in range(20):
q= rect()
assert is_square(*q), "{:d} {:s}".format(i, str(q))
for i in range(20000):
q= norect()
s1 = is_square(*q)
s2 = is_square0(*q)
assert s1 == s2, str(s1) + " " + str(s2) + " " + str(q)
print "OK"