# Enigmatic Code

Programming Enigma Puzzles

## Enigma 982: Break even

From New Scientist #2137, 6th June 1998 [link]

In a recent frame of snooker “Earthquake” Endry and “Polly” Parrot had a close contest.

Earthquake went first, and each time either player visited the table the number of balls potted was the same (and the same for both players). And each time Earthquake potted a red he followed it by attempting to pot one particular colour. And each time Polly potted a red he followed it by attempting to pot one particular colour.

Building up to a grand climax, Earthquake potted the pink but was still behind. He then potted the black to win.

That’s not enough information for you to be able to answer the following question, but if I told you whether or not two consecutive pots were ever the same colour then you would have enough information to answer the question.

What was the final score in points?

(Remember, in snooker there are 15 reds. The potting of a red earns one point and enables the player to try to pot one of the other six colours, earning from 2 to 7 points. A successful pot means that the player can try for another red, and so on. The reds stay down but the other colours are put back on the table. If an attempt to pot a ball fails then the other player has a turn at the table. When all 15 reds have gone and all 15 attempted pots at colours are completed, the six remaining colours are potted in order, and this time they too stay down. No other rules concern the frame described in this Enigma).

[enigma982]

### One response to “Enigma 982: Break even”

1. Jim Randell 29 November 2019 at 8:22 am

This Python program runs in 100ms.

Run: [ @repl.it ]

```from itertools import product
from enigma import irange, tuples, filter_unique, unpack, printf

# the coloured balls
colours = [ 2, 3, 4, 5, 6, 7 ]

# return an updated version of a list <s>, with value <v> at index <i>
def update(s, i, v):
s = list(s)
s[i] = v
return s

# play out the scenario
# balls = remaining balls
# k = number of balls potted per player
# cs = preferred colour for each player
# g = current go (0 = player 1, 1 = player 2)
# ps = points for each player
# ss = sequence of pots
def play(balls, k, cs, g=0, ps=[0, 0], ss=[]):
n = len(balls) + balls.count(1)
# final play?
if n == 0:
if g == 1 and ps[1] < ps[0] < ps[1] + 7:
return (tuple(ps), ss)
elif not(n < k):
# player g pots k balls
s = []
while len(s) < k:
s.append(balls[0])
balls = balls[1:]
if len(s) < k and s[-1] == 1:
s.append(cs[g])
# play the remainder
return play(balls, k, cs, g ^ 1, update(ps, g, ps[g] + sum(s)), ss + s)

# remaining balls to pot (15 reds, and then the colours)
balls = [1] * 15 + colours

# collect results
rs = list()

# consider:
# k = number of balls potted per player;
# c1, c2 = perferred colour for player 1, 2
for (k, c1, c2) in product(irange(2, 18), colours, colours):
r = play(balls, k, (c1, c2))
if r is None: continue
(ps, ss) = r
# are there two consecutive pots of the same colour?
f = any(x == y for (x, y) in tuples(ss, 2))
rs.append((k, (c1, c2), ps, f))
printf("[k={k}, cs=({c1}, {c2}), ps={ps}, f={f}]")

# find solutions unique by flag f
(rs, _) = filter_unique(rs, unpack(lambda k, cs, ps, f: f))

# output solutions
for (k, cs, ps, f) in rs:
printf("points = {ps} [k={k}, cs={cs}, f={f}]")
```

Solution: The final score was: Endry, 54 points; Parrot, 48 points.

Each player potted 12 balls on each turn. Endry’s colour was yellow (2 points). Parrot’s colour was black (7 points).

The game proceeded as follows:

E: 1, 2; 1, 2; 1, 2; 1, 2; 1, 2; 1, 2 [18 points]
P: 1, 7; 1, 7; 1, 7; 1, 7; 1, 7; 1, 7 [48 points]
E: 1, 2; 1, 2; 1, 2; 2; 3; 4; 5; 6; 7 [54 points]

In E‘s second go he pots two consecutive yellows (2 points).

There are two scenarios where there are no consecutive pots of the same colour:

4 pots per turn; E yellow (2); P brown (4); E wins, 46 – 40
4 pots per turn; E brown (4); P black (7); E wins, 62 – 61

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