# Enigmatic Code

Programming Enigma Puzzles

## Enigma 1532: Just reflecting

From New Scientist #2695, 14th February 2009 [link]

Joe has been showing Penny a few optical experiments. In one experiment he placed six mirrors vertically to form a regular hexagon with small gaps between the mirrors. Through one gap he shone a laser beam so it emerged straight from the gap diametrically opposite.

Penny then had to work out the smallest angle through which the beam must be rotated so that it emerged from the same gap as before, after being reflected just once by all six mirrors.

What was that small angle (rounded to the nearest degree)?

[enigma1532]

### 2 responses to “Enigma 1532: Just reflecting”

1. Jim Randell 3 July 2012 at 11:23 am

Here’s a numerical solution in Python (based on my less pretty Perl code that I wrote at the time). It generates closer and closer approximations to the answer and runs in 45ms.

```from math import sqrt, tan, radians
from enigma import printf

# some useful constants
r3 = sqrt(3) # root 3
hr3 = r3 / 2 # half root 3
rr3 = 1 / r3 # reciprocal root 3

# reflect a beam from x, y and angle psi
def reflect(psi, x, y, hit):

# the equation for the beam is: y' = y + (x' - x) / tan(psi)

# mirror 1: y = -(x / r3) - 1, x in (-hr3, 0)
if 1 not in hit:
x1 = ((x * t) - y - 1) / (t + rr3)
y1 = (-x1 * rr3) - 1
if -hr3 < x1 < 0: return (1, 60 - psi, x1, y1)

# mirror 2: y = -(x / r3) + 1, x in (0, hr3)
if 2 not in hit:
x1 = ((x * t) - y + 1) / (t + rr3)
y1 = (-x1 * rr3) + 1
if 0 < x1 < hr3: return (2, 60 - psi, x1, y1)

# mirror 3: x = -hr3, y in (-1/2, 1/2)
if 3 not in hit:
x1 = -hr3
y1 = ((x1 - x) * t) + y
if -0.5 < y1 < 0.5: return (3, 180 - psi, x1, y1)

# mirror 4: x = hr3, y in (-1/2, 1/2)
if 4 not in hit:
x1 = hr3
y1 = ((x1 - x) * t) + y
if -0.5 < y1 < 0.5: return (4, 180 - psi, x1, y1)

# mirror 5: y = x/r3 + 1, x in (-hr3, 0)
if 5 not in hit:
x1 = (y - (x * t) - 1) / (rr3 - t)
y1 = (x1 * rr3) + 1
if -hr3 < x1 < 0: return (5, 120 - psi, x1, y1)

# mirror 6: y = x/r3 - 1, x in (0, hr3)
if 6 not in hit:
x1 = (y - (x * t) + 1) / (rr3 - t)
y1 = (x1 * rr3) - 1
if 0 < x1 < hr3: return (6, 120 - psi, x1, y1)

# find the theta that gets close to the exit point
def solve(a, b, delta):
(x0, y0) = (0.0, 1.0)
theta = a
(t, m) = (None, None)
while True:
theta += delta
if not(theta < b): break
(x, y, psi) = (x0, y0, theta)
hit = set()
# reflect while we have unhit mirrors
while True:
r = reflect(psi, x, y, hit)
if r is None: break
(h, psi, x, y) = r

# have we hit all 6 mirrors
if len(hit) != 6: continue

# so how close to the exit point do we get?
(h, psi, x, y) = reflect(psi, x, y, set())
if h in (1, 6):
d = sqrt(pow(abs(x), 2) + pow(y + 1, 2))
# keep track of the best theta
if t is None or d < m: (t, m) = (theta, d)

return t

# make closer and closer approximations to the value
(a, b, delta) = (0.0, 60.0, 1.0)
while True:
theta = solve(a, b, delta)
printf("theta = {theta} [delta = {delta}]")
(a, b, delta) = (theta - delta, theta + delta, delta / 10)
if delta < 1e-12: break
```

Solution: The angle is approximately 9 degrees.

2. Jim Randell 3 July 2012 at 11:30 am

A geometrical way to demonstrate the solution (and to get an exact answer) is to reflect the hexagons rather than the beam of light.

The beam passes through (is reflected at) each of the mirrors (as can be seen by the numbering in the diagram):