-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathproblem177.coco
83 lines (65 loc) · 2.52 KB
/
problem177.coco
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# -*- Python -*- (Close enough)
from math import sin, cos, sqrt, asin, degrees, radians
sines = range(180) |> map$(radians ∘> sin) |> list
cosines = range(180) |> map$(radians ∘> cos) |> list
def clamp(value, lower, upper):
if value < lower:
return lower
elif value > upper:
return upper
else:
return value
class Quadrilateral:
def __init__(self, *angles):
assert len(angles) == 8
assert sum(angles) == 360
# Store the quadrilateral as a set of tuples indicating all
# rotations and reflections, so we can avoid duplicates. Very
# inefficient representation, but it's good enough for now.
self.angles = set()
for _ in range(4):
self.angles.add(angles)
self.angles.add(angles |> reversed |> tuple)
angles = angles[-2:] + angles[:-2]
self.angles = frozenset(self.angles)
def __repr__(self):
angles = self.angles$[0] |> map$(str) |> ','.join
return f"Quadrilateral({angles})"
def __eq__(self, other):
if not isinstance(other, Quadrilateral):
return False
return self.angles == other.angles
def __hash__(self):
return hash(("Quadrilateral", self.angles))
EPSILON = 10e-9
def is_integer(v):
return abs(v - round(v)) < EPSILON
all_solutions = set()
for a1 in range(1, 180):
for a2 in range(a1, 180 - a1):
for b1 in range(1, 180 - a1 - a2):
b2 = 180 - b1 - a1 - a2
for d2 in range(1, 180 - a1 - a2):
d1 = 180 - d2 - a1 - a2
c3 = 180 - a1 - a2
k = 1
l = sines[b2] * k / sines[b1]
m = sines[a2] * l / sines[a1]
n = sines[d2] * m / sines[d1]
x = sqrt(k ** 2 + n ** 2 - 2 * k * n * cosines[c3])
inner = clamp(n * sines[c3] / x, -1, 1)
c1 = degrees(asin(inner))
inner = clamp(k * sines[c3] / x, -1, 1)
c2 = degrees(asin(inner))
if is_integer(c1) and is_integer(c2):
int_c1 = int(c1 + 0.5)
int_c2 = int(c2 + 0.5)
if b2 + int_c1 >= 180 or int_c2 + d1 >= 180:
# Concave
continue
try:
q = Quadrilateral(a1, a2, b1, b2, int_c1, int_c2, d1, d2)
except AssertionError:
continue
all_solutions.add(q)
print(len(all_solutions))