# Enigmatic Code

Programming Enigma Puzzles

## Puzzle 88: Sergeant Simple in verse

From New Scientist #1140, 1st February 1979 [link]

I am Sergeant Simple and I keep the notes and diaries,
Of my boss Professor Knowall, magic name;
I do all the donkey work and help in the inquiries,
So the Prof. can close his eyes and use his brain.

But it is not only crime which occupies his mind,
For we also follow soccer here and there,
And I will tell you now of a most important find
Which made a nonsense problem crystal clear.

This is soccer for a few,
By a method which is new,
Ten and five are points awarded for a win and for a draw,
And a point for every goal that has been scored.

If you ask what this is for
I reply that that’s the law

And more goals will be obtained as the reward.

Four teams all played each other, it does not matter when,
A and C got eight points each and B nineteen, and then
One more got fifty seven. And there’s a problem rich
For one teams points are incorrect. I must not tell you which.

But Professor Knowall knows and he says this:
“If I give the information that you can discover which,
Why then you will be able so to do”.

The Professor, as we know, is good at many things,
But he has not got the fantasy that gives a poet wings.
And you can then the puzzle solve. For when
A match is played at least one goal is scored by both,
But they never scored together more than ten.

Which figure was wrong? And what information can you give about the score in each match?

[puzzle88]

### One response to “Puzzle 88: Sergeant Simple in verse”

1. Jim Randell 16 November 2016 at 9:05 am

I’m not entirely happy with this puzzle. I think the crux is deciphering the phrase: “If I give the information that you can discover which, Why then you will be able so to do”. Which I suppose is meant to tell us that the wrong total cannot be A or C. There is nothing in the puzzle text to distinguish A and C, so for any solution that involves A there will be a corresponding solution involving C where the labels for A and C are swapped.

This means we only need to consider B and D as the incorrect scores.

This Python program uses the Football() helper class from the enigma.py library to consider possible match outcomes. It runs in 991ms.

```from itertools import product
from collections import defaultdict
from enigma import Football, irange, printf

# scoring system (we'll add the points for the goals separately)
football = Football(games='wdl', points={ 'w': 10, 'd': 5 })

# the points we are given (but one of them is wrong)
points = { 'A': 8, 'B': 19, 'C': 8, 'D': 57 }

# possible scores in the matches
scores = dict()
scores['d'] = list((a, a) for a in irange(1, 5))
scores['w'] = list((a, b) for a in irange(2, 9) for b in irange(1, min(a - 1, 10 - a)))
scores['l'] = list((b, a) for (a, b) in scores['w'])

# record possible wrong scores
r = defaultdict(set)

# possible matches
for (AB, AC, AD, BC, BD, CD) in football.games(repeat=6):

# make the tables
A = football.table([AB, AC, AD], [0, 0, 0])
B = football.table([AB, BC, BD], [1, 0, 0])
C = football.table([AC, BC, CD], [1, 1, 0])
D = football.table([AD, BD, CD], [1, 1, 1])

# consider which team we've been given wrongly
for (i, wrong) in enumerate('ABCD'):
# only consider B and D
if wrong == 'A' or wrong == 'C': continue

# the remaining scores we are given are correct
# and each team scores at least 1 goal in each match
if any(table.points + 3 > points[name] for (table, name) in zip((A, B, C, D), 'ABCD') if name != wrong):
continue

# consider matches for A
# goals for/against for A
(fA, aA) = football.goals([sAB, sAC, sAD], [0, 0, 0])
# check
if wrong != 'A' and A.points + fA != points['A']: continue

# consider remaining matches for B
for (sBC, sBD) in product(scores[BC], scores[BD]):
# goals for/against for B
(fB, aB) = football.goals([sAB, sBC, sBD], [1, 0, 0])
# check
if wrong != 'B' and B.points + fB != points['B']: continue

# consider remaining match
for sCD in scores[CD]:
# goals for/against C
(fC, aC) = football.goals([sAC, sBC, sCD], [1, 1, 0])
# check
if wrong != 'C' and C.points + fC != points['C']: continue
# goals for/against D
# check
if wrong != 'D' and D.points + fD != points['D']: continue

# record the wrong score
pts = ((A, B, C, D)[i]).points + (fA, fB, fC, fD)[i]

printf("A={A} f={fA} a={aA}")
printf("B={B} f={fB} a={aB}")
printf("C={C} f={fC} a={aC}")
printf("wrong={wrong}, should be {pts}")
printf()

for (k, v) in r.items():
printf("wrong={k}, points={v}", v=sorted(v))
```

Solution: The score for B was wrong.

The score for B should be between 25 and 39.

There are 64 different ways to achieve this:

For each of 25 and 39 there is 1 possible set of match outcomes.
For 26 and 38 there are 2.
For 27 and 37 there are 3.
For 28 and 36 there are 4.
For 29 and 35 there are 5.
For 30 and 34 there are 6.
For 31 and 33 there are 7.
For 32 there are 8.

Possible scores are:

A vs B: 1-2, 1-3, 1-4, 1-5, 1-6, 1-7, 1-8, 1-9.
A vs C: 1-1.
A vs D: 1-9.
B vs C: 2-1, 3-1, 4-1, 5-1, 6-1, 7-1, 8-1, 9-1.
B vs D: 1-9.
C vs D: 1-9.

The 8 possibilities for A vs B multiplied by the 8 possibilities for B vs C give the 64 possible combinations.

If the scores for either A or C were wrong there would be 109 possible sets of match outcomes in each case.

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