62 lines
1.8 KiB
Python
62 lines
1.8 KiB
Python
from math import sqrt, pi, atan
|
|
|
|
|
|
def get_intersection(n: int) -> tuple[int, int]:
|
|
"""Compute the point where the line intersects the circle for a given
|
|
number of circles `n`.
|
|
|
|
Equation for circle: y = 1 - sqrt(2*x - x**2)
|
|
Equation for line: y = (1/n) * x
|
|
"""
|
|
|
|
# Computed via Wolfram alpha; could be derived by setting the curves equal,
|
|
# isolating the root, and then applying the quadratic formula.
|
|
x_int = (-sqrt(2) * n ** (3 / 2) + n**2 + n) / (n**2 + 1)
|
|
y_int = x_int / n
|
|
return (x_int, y_int)
|
|
|
|
|
|
def get_ratio_orange(n: int) -> float:
|
|
"""Compute the ratio between the orange and the blue section. The blue
|
|
section is the L-section meaning the area outside of the quarter circle.
|
|
The orange area is the concave triangle created by the diagonal line."""
|
|
|
|
x, y = get_intersection(n)
|
|
area_blue = 1 - (pi / 4)
|
|
|
|
theta = atan((1 - x) / (1 - y)) # angle of concave triangle circle part
|
|
area_sector = theta / 2 # area of sector of concave triangle circle part
|
|
|
|
# area_orange = area triangle + area_rectangle + area_triangle - area_sector
|
|
area_orange = (0.5 * x * y) + ((1 - x) * y) + (0.5 * (1 - x) * (1 - y))
|
|
area_orange -= area_sector
|
|
return area_orange / area_blue
|
|
|
|
|
|
def get_less_than(percentage: float) -> int:
|
|
ratio = percentage / 100
|
|
n_min, n_max = 1, 10000
|
|
|
|
while n_max - n_min > 1:
|
|
n_mid = (n_max + n_min) // 2
|
|
ratio_n = get_ratio_orange(n_mid)
|
|
if ratio_n < ratio:
|
|
n_max = n_mid
|
|
else:
|
|
n_min = n_mid
|
|
|
|
return n_max
|
|
|
|
|
|
def euler_587():
|
|
assert get_ratio_orange(1) == 0.5
|
|
assert abs(get_ratio_orange(2) - 0.3646) <= 0.0001
|
|
assert get_less_than(10) == 15
|
|
return get_less_than(0.1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
solution = euler_587()
|
|
print(f"e587.py: {solution}")
|
|
assert solution == 2240
|