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]

Advertisements

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)
      t = 1 / tan(radians(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
          hit.add(h)
    
        # 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):

    The exact answer is then: θ = arctan(sqrt(3) / 11)

    Which is (approximately) 8.948275564627°.

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: