Skip to content

Commit 8c13a77

Browse files
fpringlegithub-actions
and
github-actions
authored
feat: add solution for Project Euler problem 144 (TheAlgorithms#4280)
* Added solution for Project Euler problem 144 * updating DIRECTORY.md * Better variable names * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
1 parent 256c319 commit 8c13a77

File tree

3 files changed

+103
-0
lines changed

3 files changed

+103
-0
lines changed

DIRECTORY.md

+2
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,8 @@
788788
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_129/sol1.py)
789789
* Problem 135
790790
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_135/sol1.py)
791+
* Problem 144
792+
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_144/sol1.py)
791793
* Problem 173
792794
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_173/sol1.py)
793795
* Problem 174

project_euler/problem_144/__init__.py

Whitespace-only changes.

project_euler/problem_144/sol1.py

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
"""
2+
In laser physics, a "white cell" is a mirror system that acts as a delay line for the
3+
laser beam. The beam enters the cell, bounces around on the mirrors, and eventually
4+
works its way back out.
5+
6+
The specific white cell we will be considering is an ellipse with the equation
7+
4x^2 + y^2 = 100
8+
9+
The section corresponding to −0.01 ≤ x ≤ +0.01 at the top is missing, allowing the
10+
light to enter and exit through the hole.
11+

12+
The light beam in this problem starts at the point (0.0,10.1) just outside the white
13+
cell, and the beam first impacts the mirror at (1.4,-9.6).
14+
15+
Each time the laser beam hits the surface of the ellipse, it follows the usual law of
16+
reflection "angle of incidence equals angle of reflection." That is, both the incident
17+
and reflected beams make the same angle with the normal line at the point of incidence.
18+
19+
In the figure on the left, the red line shows the first two points of contact between
20+
the laser beam and the wall of the white cell; the blue line shows the line tangent to
21+
the ellipse at the point of incidence of the first bounce.
22+
23+
The slope m of the tangent line at any point (x,y) of the given ellipse is: m = −4x/y
24+
25+
The normal line is perpendicular to this tangent line at the point of incidence.
26+
27+
The animation on the right shows the first 10 reflections of the beam.
28+
29+
How many times does the beam hit the internal surface of the white cell before exiting?
30+
"""
31+
32+
33+
from math import isclose, sqrt
34+
35+
36+
def next_point(
37+
point_x: float, point_y: float, incoming_gradient: float
38+
) -> tuple[float, float, float]:
39+
"""
40+
Given that a laser beam hits the interior of the white cell at point
41+
(point_x, point_y) with gradient incoming_gradient, return a tuple (x,y,m1)
42+
where the next point of contact with the interior is (x,y) with gradient m1.
43+
>>> next_point(5.0, 0.0, 0.0)
44+
(-5.0, 0.0, 0.0)
45+
>>> next_point(5.0, 0.0, -2.0)
46+
(0.0, -10.0, 2.0)
47+
"""
48+
# normal_gradient = gradient of line through which the beam is reflected
49+
# outgoing_gradient = gradient of reflected line
50+
normal_gradient = point_y / 4 / point_x
51+
s2 = 2 * normal_gradient / (1 + normal_gradient * normal_gradient)
52+
c2 = (1 - normal_gradient * normal_gradient) / (
53+
1 + normal_gradient * normal_gradient
54+
)
55+
outgoing_gradient = (s2 - c2 * incoming_gradient) / (c2 + s2 * incoming_gradient)
56+
57+
# to find the next point, solve the simultaeneous equations:
58+
# y^2 + 4x^2 = 100
59+
# y - b = m * (x - a)
60+
# ==> A x^2 + B x + C = 0
61+
quadratic_term = outgoing_gradient ** 2 + 4
62+
linear_term = 2 * outgoing_gradient * (point_y - outgoing_gradient * point_x)
63+
constant_term = (point_y - outgoing_gradient * point_x) ** 2 - 100
64+
65+
x_minus = (
66+
-linear_term - sqrt(linear_term ** 2 - 4 * quadratic_term * constant_term)
67+
) / (2 * quadratic_term)
68+
x_plus = (
69+
-linear_term + sqrt(linear_term ** 2 - 4 * quadratic_term * constant_term)
70+
) / (2 * quadratic_term)
71+
72+
# two solutions, one of which is our input point
73+
next_x = x_minus if isclose(x_plus, point_x) else x_plus
74+
next_y = point_y + outgoing_gradient * (next_x - point_x)
75+
76+
return next_x, next_y, outgoing_gradient
77+
78+
79+
def solution(first_x_coord: float = 1.4, first_y_coord: float = -9.6) -> int:
80+
"""
81+
Return the number of times that the beam hits the interior wall of the
82+
cell before exiting.
83+
>>> solution(0.00001,-10)
84+
1
85+
>>> solution(5, 0)
86+
287
87+
"""
88+
num_reflections: int = 0
89+
point_x: float = first_x_coord
90+
point_y: float = first_y_coord
91+
gradient: float = (10.1 - point_y) / (0.0 - point_x)
92+
93+
while not (-0.01 <= point_x <= 0.01 and point_y > 0):
94+
point_x, point_y, gradient = next_point(point_x, point_y, gradient)
95+
num_reflections += 1
96+
97+
return num_reflections
98+
99+
100+
if __name__ == "__main__":
101+
print(f"{solution() = }")

0 commit comments

Comments
 (0)