# Enigmatic Code

Programming Enigma Puzzles

## Enigma 1366: Done in half the time

From New Scientist #2525, 12th November 2005

At various times during last Saturday and Sunday (always at an exact number of minutes before or after an hour) I looked at my smooth-running watch. On the first occasion I noted the angle between the hour hand and the minute hand. When I looked again some time later the angle had halved. When I looked again some time later the angle had halved again. When I looked again some time later the angle had halved again. When I looked again some time later the angle had halved again. When I looked again some time later the angle had halved again. When I looked again some time later the angle had halved again. When I looked again some time later the angle had halved again. When I looked again some time later the angle had halved again.

At what time did I last look at my watch?

[enigma1366]

### One response to “Enigma 1366: Done in half the time”

1. Jim Randell 8 December 2013 at 9:07 am

This Python program calculates possible sequences of times. It runs in 61ms.

```from collections import defaultdict
from enigma import irange, sprintf, printf

# turn a sequence of time choices into a sequence of actual times
# ts - sequence of time choices
# ss - sequence of actual times
def solve(ts, ss):
# are we done?
if not ts:
yield ss
else:
# choose a time
for t in ts[0]:
if not ss:
# start in phase 0
yield from solve(ts[1:], [(t, 0)])
else:
phase = ss[-1][1]
if t > ss[-1][0]:
yield from solve(ts[1:], ss + [(t, phase)])
elif phase < 3:
yield from solve(ts[1:], ss + [(t, phase + 1)])

# the four possible phases
phases = [ 'am Sat', 'pm Sat', 'am Sun', 'pm Sun' ]

# output format for a sequence of times
def output(ss):
return ', '.join(sprintf("{t[0]}:{t[1]:02d}{p}", p=phases[p]) for (t, p) in ss)

# consider 12 hours in minutes
# and record the angle in 720ths of the full circle (half degrees)
# map: angle -> times
d = defaultdict(list)
for h in irange(0, 719):
m = 12 * (h % 60)
a = abs(h - m)
if a > 360: a = 720 - a
d[a].append(h)

# count solutions by final time
r = defaultdict(int)
# go through keys in order
for k in sorted(d.keys()):
# look for multiples of the keys
ks = list(k * pow(2, n) for n in irange(8, 0, -1))
if ks[0] > 360: break
if not all(m in d for m in ks): continue
# find the corresponding possible times
ts = list(list(divmod(t, 60) for t in d[m]) for m in ks)
# and construct sequences of actual times within 4 phases
for ss in solve(ts, []):
r[ss[-1]] += 1
printf("[{ss}]", ss=output(ss))

for (k, v) in r.items():
printf("{k} [{v} solutions]", k=output([k]))
```

Solution: You last looked at your watch at 9:49pm on Sunday.

I was half-hoping that there would be some sneaky solution to do with putting the clocks back from BST to GMT (if the watch was a radio controlled watch it would happen automatically at 2:00am on Sunday morning, being changed to 1:00am on Sunday morning). But there aren’t any candidate times that work.

Analytically we can see there are 12×60 = 720 positions for the hour hand in any 12-hour period. The program above calculates the angular difference between the hour and minute hand for each of these positions using units of 1/720th of a full circle, or ½°. Clearly the maximum angular difference is 360 (=180°) and whatever the final angle is we need to know the time at 2×, 4×, 8×, 16×, 32×, 64×, 128× and 256× this value. But for 256× the final angle to be 360 or less the final angle can only be 0 or 1.

The degenerate solution of 0 doesn’t work, as there is only one time where this works – 12:00. And we can’t fit 9 of them into four phases of the clock. However if the final angle is 1 (=½°), then each multiple of the angle has two possible choices. In fact it turns out there are 128 possible sequences of times that will fit within four phases of the clock, and for all of these the final time is 9:49pm on Sunday.

Here’s a diagram of one possible sequence of times. The setter must be very good at assessing small angles.