# Enigmatic Code

Programming Enigma Puzzles

## Enigma 482: Hopscotch

From New Scientist #1633, 8th October 1988 [link]

I remember playing a version of hopscotch when I was a child. We used a chalked outline like the one shown, and there were various games we could play on it. The simplest one was to start where shown and throw a pebble towards number 1 and then hop to the pebble: then throw it towards number 2 and hop to it, and so on, finally throwing the pebble towards number 9 and hopping to the pebble. You scored 1 if the pebble landed on the correct number, ½ if it missed by one, ⅓ if it missed it by two, and so on, making 9 the maximum possible total score. You were disqualified if the pebble didn’t land on a numbered square.

When I first tried the game I was pretty hopeless. When throwing at number 1 the pebble went past it. I hopped to the pebble, threw the pebble towards number 2, and continued in this way to complete the game. On no occasion was I standing on the square which I should be aiming at and, apart from when the pebble went past number 1 on my first throw, on only one other occasion did the pebble go too far and go past the square I was aiming at. I ended up with the pebble landing on all the squares from 1 to 9 (albeit in the wrong order) and my score was a whole number.

In what order did I visit the squares?

The issue date of New Scientist that this puzzle was published in falls on a Saturday, the issue date of previous magazines fell on a Thursday, so the date of this issue is 9 days after the date of the previous issue.

[enigma482]

### 3 responses to “Enigma 482: Hopscotch”

1. Jim Randell 7 January 2019 at 7:41 am

This Python 3 program uses a recursive function to generate possible sequences of squares that satisfy the movements required. Only one of them comes out with an integer score. It runs in 79ms.

Run: [ @repl.it ]

```from enigma import irange, mlcm, printf

# ss - sequence of squares
# n - target square (= go number)
# s - sequence so far
# k - remaining overshoots
def solve(ss, n, s, k):
# are we done?
if n == 10:
if k == 0:
yield s
else:
# current position
p = s[-1]
# cannot be the target
if p == n: return
# choose an onward square
for x in ss:
# each square is only visited once
if x in s: continue
# aiming towards the current target
if (p - x) * (p - n) < 0: continue
# is it an overshoot?
f = (x < n < p or x > n > p)
if f and k < 1: continue
# check the remaining squares
yield from solve(ss, n + 1, s + [x], k - f)

# possible squares
squares = list(irange(1, 9))

# common denominator for scores
k = mlcm(*squares)

# first square is an overshoot
for x in irange(2, 9):
# consider remaining squares
for s in solve(squares, 2, [x], 1):
# number of points for this game
t = sum(k // (abs(x - i) + 1) for (i, x) in enumerate(s, start=1))
# is a whole number
(t, r) = divmod(t, k)
if r != 0: continue
printf("{s} = {t} points")
```

Solution: The order the squares were visited was: 6, 4, 1, 2, 3, 5, 7, 8, 9.

Which gives a score of 1/6 + 1/3 + 1/3 + 1/3 + 1/3 + 1/2 + 1 + 1 + 1 = 5.

There are 32 other sequences that satisfy the conditions of the puzzle text, but give non-integer scores.

2. Brian Gladman 7 January 2019 at 6:24 pm
```from math import gcd

def solve(target, tf_cnt, visited):
# if all bases have been visited
if target == 10:
# ... and exactly two throws go too far
if tf_cnt == 2:
# return the sequence in which the bases are visited
yield visited
else:
pos = visited[-1]
# the current position must not be the target
if pos != target:
# consider possible next positions
for next_pos in set(range(1, 10)).difference(visited):
# find the ratio of the distance to the next position
# over the distance to the target
tf = (next_pos - pos) / (target - pos)
tfc = tf_cnt + (tf > 1.0)
# the throw must be towards the target and there
# cannot be more than two throws that go too far
if tf > 0 and tfc < 3:
yield from solve(target + 1, tfc, visited + (next_pos,))

# compute the score for a game
def score(visited):
t, b = 0, 1
for i, j in enumerate(visited, 1):
x = abs(i - j) + 1
t, b = t * x + b, b * x
g = gcd(t, b)
return t // g, b // g

sol = 0
# the first throw goes too far
for first in range(2, 10):
# find possible sequences in which the bases are visited
for v in solve(2, 1, (first,)):
# compute the score (t / b)
t, b = score(v)
print(f'sequence (score {t}/{b}) = {v}')
# find the score as an integer and remainder
q, r = divmod(*score(v))
if not r:
sol = (q, v)
print(f'\rSolution sequence (score {sol[0]}) = {sol[1]}')
```
3. Hugh Casement 7 January 2019 at 7:40 pm

From this issue onward, New Scientist bore a Saturday date, previously Thursday.
It seems to have reverted to Friday from May 2018
(but the last Enigma appeared in 2013).

This site uses Akismet to reduce spam. Learn how your comment data is processed.