Enigmatic Code

Programming Enigma Puzzles

Enigma 968: One match decides all

From New Scientist #2123, 28th February 1998 [link]

Albion, Borough, City, Rangers and United have played another tournament in which each team played each of the other teams once. Three points were awarded for a win and one point to each team for a draw.

On points gained, the teams finished in the order: Albion, Borough, City, Rangers, United. Each team gaining a different number of points. Each team won at least one match and lost at least one match.

If I told you the result of one particular match in the tournament you would be able to deduce with certainty the results of all the other matches.

Which particular match, and what was the result?


One response to “Enigma 968: One match decides all

  1. Jim Randell 20 March 2020 at 7:48 am

    This Python program runs in 112ms.

    Run: [ @repl.it ]

    from enigma import subsets, irange, filter_unique, map2str, printf
    # possible points awarded per match
    outcomes = dict(w=(3, 0), d=(1, 1), l=(0, 3))
    # calculate the points:
    # - there must be at least one win (= 3 points)
    # - there must be at least one loss (= 0 points)
    def points(ms, ts):
      ps = list(outcomes[m][t] for (m, t) in zip(ms, ts))
      if not(3 in ps and 0 in ps): return None
      return sum(ps)
    # record possible matches
    ms = list()
    # choose outcomes for U's matches
    for (AU, BU, CU, RU) in subsets("wdl", size=4, select="M"):
      U = points([AU, BU, CU, RU], [1, 1, 1, 1])
      if U is None: continue
      # choose coutcomes for R's remaining matches
      for (AR, BR, CR) in subsets("wdl", size=3, select="M"):
        R = points([AR, BR, CR, RU], [1, 1, 1, 0])
        if R is None or not(R > U): continue
        # choose outcomes for C's remaining matches
        for (AC, BC) in subsets("wdl", size=2, select="M"):
          C = points([AC, BC, CR, CU], [1, 1, 0, 0])
          if C is None or not(C > R): continue
          # choose outcome for the remaining match
          for AB in "wdl":
            B = points([AB, BC, BR, BU], [1, 0, 0, 0])
            if B is None or not(B > C): continue
            A = points([AB, AC, AR, AU], [0, 0, 0, 0])
            if A is None or not(A > B): continue
            ms.append((AB, AC, AR, AU, BC, BR, BU, CR, CU, RU))
    # find which match fixes all the others
    labels = "AB AC AR AU BC BR BU CR CU RU".split()
    for i in irange(0, 9):
      (ss, _) = filter_unique(ms, (lambda m: m[i]))
      for s in ss:
        printf("{k}={v} -> {s}", k=labels[i], v=s[i], s=map2str(zip(labels, s)))

    Solution: If we are told that Rangers beat Borough then we can deduce the outcomes of all the other matches.

    The outcomes of all the matches are:

    A vs B = win for B
    A vs C = win for A
    A vs R = win for A
    A vs U = win for A
    B vs C = draw
    B vs R = win for R
    B vs U = win for B
    C vs R = draw
    C vs U = win for C
    R vs U = win for U

    And the points are:

    A = 9
    B = 7
    C = 5
    R = 4
    U = 3

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 )

Google photo

You are commenting using your Google 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 )

Connecting to %s

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

%d bloggers like this: