Enigmatic Code

Programming Enigma Puzzles

Puzzle 78: Football: new method

From New Scientist #1129, 16th November 1978 [link]

Three teams, AB and C are all to play each other once at football. 10 points are given for a win, 5 points for a draw and 1 point for each goal scored whatever the result of the match. After some, or perhaps all, the matches have been played the points were as follows:

A   21
B   20
C    4

Not more than 6 goals were scored in any match.

What was the score in each match?

[puzzle78]

Advertisements

2 responses to “Puzzle 78: Football: new method

  1. Jim Randell 15 March 2017 at 9:38 am

    This is a similar puzzle to Enigma 239 (there are only 3 teams in this version). But because of the smaller solution space an even simpler approach suffices (and is slightly faster with a slightly shorter program).

    This Python 3 program runs in 66ms

    from itertools import product
    from enigma import Football, printf
    
    # scoring system (we'll add in the points for the goals separately)
    football = Football(points={ 'w': 10, 'd': 5 })
    
    # score lines with not more than 6 goals scored
    _scores = {
      'x': [None],
      'd': [(0, 0), (1, 1), (2, 2), (3, 3)],
      'w': [
        (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0),
        (2, 1), (3, 1), (4, 1), (5, 1),
        (3, 2), (4, 2)
      ]
    }
    _scores['l'] = list((y, x) for (x, y) in _scores['w'])
    
    # possible scores for given match outcomes
    def scores(ms):
      for m in ms:
        yield from _scores[m]
    
    # return points (including points for goals)
    def points(ss, ts):
      t = football.table(football.outcomes(ss), ts)
      (f, a) = football.goals(ss, ts)
      return t.points + f
        
    # matches for C (4 points, so no wins and no draws)
    for (AC, BC) in product(scores('wx'), repeat=2):
      # check points for C
      if points([AC, BC], [1, 1]) != 4: continue
    
      # the remaining match
      for AB in scores('wdlx'):
        # check points for A
        if points([AB, AC], [0, 0]) != 21: continue
        # check points for B
        if points([AB, BC], [1, 0]) != 20: continue
    
        printf("AB={AB} AC={AC} BC={BC}")
    

    Solution: The scores in the matches are: A v B = 2-2; A v C = 4-2; B v C = 3-2.

    • Jim Randell 15 March 2017 at 9:58 pm

      Analytically:

      C cannot win or draw either of their games (A v C, B v C). Their 4 points can only come from goals scored.

      As it is not possible to gain 20 or 21 points from a single game with no more than six goals scored it means that A must win A v C and B must win B v C and the other match (A v B) must be played. Neither side can win the A v B match and only have 20 or 21 points, so the match must be drawn.

      So A and B have 15 points each from match outcomes, and C has 0 points. Their remaining points come from goals scored: A scores 6, B scores 5, C scores 4.

      The score in the A v B match is one of: 0-0, 1-1, 2-2, 3-3.

      Considering A v B = 0-0:

      A’s goals must all be scored in the A v C match, so A must win that match 6-0. So the score in the B v C match must be 5-4, but this is not possible as no match has more than 6 goals scored in it. So A v B = 0-0 is not possible.

      We can similarly eliminate A v B = 1-1 and A v B = 3-3.

      This leaves A v B = 2-2, and the only possible scores for the other matches are A v C = 4-2, B v C = 3-2.

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: