# Enigmatic Code

Programming Enigma Puzzles

## Enigma 1447: Bonus points

From New Scientist #2608, 16th June 2007

Albion, Borough, City, Rangers and United have played another tournament in which each team played each of the others once, two matches being played on each of five successive Saturdays, each team having one Saturday without a match. Points were awarded according to a formula now widely used in Rugby: 4 points for a win, 2 points to each team for a draw, and in any match either team or both teams might also gain 1 bonus point.

After the first Saturday’s match Albion led the tournament, followed in order by Borough, City, Rangers and United, 1 point separating each pair of successive teams. After the second Saturday’s matches 1 point still separated each pair of successive teams, but no team was in the same position as after the first Saturday’s matches.

If I identified my team and told you what position it was in after the second Saturday’s matches you could deduce with certainty which matches had been played on that day and how many points each team had gained in them.

Which matches were played on the second Saturday, and how many points did each team gain in them?

[enigma1447]

### One response to “Enigma 1447: Bonus points”

1. Jim Randell 25 March 2013 at 10:17 am

This Python program examines all possible outcomes for the second Saturday. It runs in 47ms.

It uses the partitions() function added to the enigma.py library for Enigma 1449 (and Enigma 70).

```from itertools import combinations, product
from collections import defaultdict
from enigma import diff, partitions, printf

# after the first Saturday the order is:
# A > B > C > R > U
# but one team hasn't played yet, so has 0 points, so:
# A = 4 > B = 3 > D = 2 > R = 1 > U = 0
# hence the matches were:
# A vs R: A won (4 points), R bonus (1 point)
# B vs C: draw, B bonus (3 points), C (2 points)

# teams
teams = tuple('ABCRU')

# possible scores for a match, including bonus points
match = (
(4, 0), (5, 0), (4, 1), (5, 1),
(2, 2), (3, 2), (2, 3), (3, 3),
(0, 4), (1, 4), (0, 5), (1, 5),
)

played = set((('A', 'R'), ('B', 'C')))

# record results by team and position
r = defaultdict(list)
# choose the team that doesn't play (from A, B, C, R)
for n in diff(teams, 'U'):
# pair up the remaining teams
for (m1, m2) in partitions(diff(teams, n), 2):
# don't repeat any matches
if m1 in played or m2 in played: continue
for (s1, s2) in product(match, repeat=2):
# scores after the first round
s = { 'A': 4, 'B': 3, 'C': 2, 'R': 1, 'U': 0 }
# add in the second round scores
s[m1[0]] += s1[0]
s[m1[1]] += s1[1]
s[m2[0]] += s2[0]
s[m2[1]] += s2[1]
# what are the points?
pts = s.values()
# pts values should be distinct
if len(set(pts)) != 5: continue
# the teams should be 1 point apart
if max(pts) - min(pts) != 4: continue
# what order are the teams in?
t = sorted(s.keys(), key=lambda x: s[x], reverse=True)
if any(t[i] == x for (i, x) in enumerate(teams)): continue
# record results by team and position
for p in enumerate(t):
r[p].append((m1, s1, m2, s2))

# look for results that give a unique solution
for (k, v) in r.items():
if len(v) != 1: continue
(m1, s1, m2, s2) = v[0]
printf("{k[1]} #{r} => {m1[0]} vs {m1[1]}: {s1[0]}pts, {s1[1]}pts / {m2[0]} vs {m2[1]}: {s2[0]}pts, {s2[1]}pts", r=k[0] + 1)
```

Solution: The matches on the second Saturday are as follows – Borough plays United, each side gains 3 points (so the match is drawn and each side is awarded a bonus point); City plays Rangers, Rangers gains 4 points, City gains no points (so Rangers won the match and no bonus points are awarded).

Although the participants and points are uniquely determined, the setters team and position on the second Saturday are not. There are three possible solutions – the setter supports United and they are placed 4th; the setter supports Rangers and they are placed 2nd; the setter supports Borough and they are placed 1st.

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