# Enigmatic Code

Programming Enigma Puzzles

## Enigma 383: Stop watch

From New Scientist #1532, 30th October 1986 [link]

My watch is pretty accurate — when it’s working. It has a sweep second-hand that advances in jerks, one each second; if the watch stops, it stops with the second hand pointing directly to one of the 60 “second” (or “minute”) marks round the rim. At noon all three hands are (naturally) pointing directly to the zero-minute mark.

At noon yesterday my watch was certainly working, but when I checked it at 6:00 pm I found that it had stopped. The angles the three hands made with each other all differed from 120 degrees by less than 1 degree.

At what time had my watch stopped? (Hours : minutes : seconds).

[enigma383]

### 2 responses to “Enigma 383: Stop watch”

1. Jim Randell 10 February 2017 at 6:23 am

I always thought a “sweep second hand” meant that the second hand moved continuously (or in small enough increments it appears to be continuous). But it doesn’t. It means the second hand is on the same dial as the hour and minute hands (instead of having its own separate little dial). So it is possible to have a “sweep second hand” that “advances in jerks”.

This Python program runs in 264ms.

```from fractions import Fraction as F
from enigma import irange, printf

# the span of the hands
def span(a, b):
d = abs(a - b)
return (1 - d if 2 * d > 1 else d)

# turn a fraction of a circle into degrees
def degrees(f):
return 360 * f

# check the span is in the desired range
def check(a, b):
return 119 < degrees(span(a, b)) < 121

# consider value for seconds
for S in irange(0, 59):

# position of the second hand (fraction of a full circle)
s = F(S, 60)

# consider value for minutes
for M in irange(0, 59):

# position of the minute hand
m = F(M, 60) + F(s, 60)

# is this a span we are interested in?
if not check(s, m): continue

# consider values for hours
for H in irange(0, 5):

# position of the hour hand
h = F(H, 12) + F(m, 12)

# is this a span we are interested in?
if not(check(h, m) and check(h, s)): continue

printf("{H:02d}:{M:02d}:{S:02d} h={h:.2f} m={m:.2f} s={s:.2f}", h=float(degrees(h)), m=float(degrees(m)), s=float(degrees(s)))
```

Solution: The watch had stopped at 5:49:09 pm.

A similar configuration would also occur at 6:10:51 pm (which is close to being a vertical reflection of the solution), but these are the only two times that work.

• Jim Randell 10 February 2017 at 6:26 am

If we choose a position for the second hand, then this defines two narrow regions that the minute hand can fall in, and if we find a suitable position for the minute hand this gives a single narrow region that the hour hand can fall in.

This Python program uses this approach, so considers fewer possibilities. I also expanded the equations so that everything is calculated using integers. It runs in 39ms.

```from enigma import irange, divc, divf, printf

# regions
regions = (
# s -> m is approx 120 degrees
# s -> h is approx 240 degrees
# abs(m -> h) is approx 120 degrees
(120, 240, 120),
# s -> m is approx 240 degrees
# s -> h is approx 120 degrees
# abs(m -> h) is approx 120 degrees
(240, 120, 120),
)

# consider value for seconds
for S in irange(0, 59):

for (a, b, c) in regions:

# construct the regions (allow 1 degree either side)
(a1, b1, c1) = (d - 1 for d in (a, b, c))
(a2, b2, c2) = (d + 1 for d in (a, b, c))

# find minute values at a1 < m < a2 degrees further on
# s = S/60
# m = M/60 + s/60 = M/60 + S/3600
# a1 < 360(m - s) < a2
# a1 < 360(M/60 + S/3600 - S/60) < a2
# a1 < 6M + S/10 - 6S < a2
# a1 < 6M - 59S/10 < a2
# (10a1 + 59S)/60 < M < (10a2 + 59S)/60

x = 59 * S
for M in irange(divc(10 * a1 + x + 1, 60), divf(10 * a2 + x - 1, 60)):
M = M % 60

# find hour values at b1 < h < b2 degrees further on
# h = H/12 + m/12 = H/12 + M/720 + S/43200
# b1 < 360(h - s) < b2
# b1 < 360(H/12 + M/720 + S/43200 - S/60) < b2
# b1 < 30H + M/2 + S/120 - 6S) < b2
# b1 < 30H + M/2 - 719S/120 < b2
# 120b1 < 3600H + 60M - 719S < 120b2
# (120b1 - 60M + 719S)/3600 < H < (120b2 - 60M + 719S)/3600

x = 719 * S - 60 * M
for H in irange(divc(120 * b1 + x + 1, 3600), divf(120 * b2 + x - 1, 3600)):
H = H % 12
if H > 5: continue

# finally check the angle between the minute and hour hands
# c1 < 360 abs(m - h) < c2
# c1 < 360 abs(M/60 + S/3600 - H/12 - M/720 - S/43200) < c2
# c1 < abs(11M/2 + 11S/120 - 30H) < c2
# 120c1 < abs(660M + 11S - 3600H) < 120c2

if 120 * c1 < abs(660 * M + 11 * S - 3600 * H) < 120 * c2:
# output a solution time
printf("{H:02d}:{M:02d}:{S:02d}")
```

We can find the further solution by removing the restriction on H at line 49.

My previous version considered the 60 possibilities for S, and for each of those tried the 60 possibilities for M. Out of the 3600 possibilities, 38 of them prove to be viable, and for each viable possibility the 6 values for H are tried.

This program considers the 60 possible positions of the second hand, and for each one it looks to see if the minute hand can be positioned in a region either 120° or 240° further on. So instead of 3600 possibilities it only tries 120 (and finds the same 38 viable pairs), then for each of those possibilities it looks to position the hour hand in the other region, and if that proves to be possible we finally check that the angle between the hour and minute hands is within the required range.

Even though this approach is faster I think the original program is fast enough, and probably easier to modify to accommodate problems of a similar nature. (And both approaches are, of course, faster than just trying all possible 6 × 60 × 60 = 21,600 possible hand positions).