Brain teaser 983: Superchamp
From The Sunday Times, 24th May 1981 [link]
The five champion athletes competed against one another in their five special events to decide who was the supreme champion (the one with the highest number of points). Three points were awarded for the winner in each event. two points for second place, and one for third.
The Superchamp won more events than anyone else. All scored a different number of points, and all scored in a different number of events.
Ben and Colin together scored twice as many points as Fred. Eddie was the only one to win his own special event, and in it the Superchamp came second. In another event Eddie gained one point less than the hurdler. The hurdler only came third in the hurdles, which was won by Denis, who was last in the long jump but scored in the sprint.
Fred won the long jump and was second in the walk, but came nowhere in the hurdles.Ben scored in the long jump and Colin scored in the sprint. The thousand-metre man was third in two events. The long jumper scored more points than the sprinter.
Who was the [long] jumper, and what was his score?
This puzzle is included in the book The Sunday Times Book of Brainteasers (1994).
[teaser983]

Jim Randell 3:35 pm on 14 January 2026 Permalink |
There are a lot of conditions to this puzzle, so I used the minizinc.py library to allow me to construct a declarative model for it in MiniZinc, which is then solved, and the Python program used to format the solutions.
It runs in 545ms.
from enigma import (require, printf) from minizinc import MiniZinc require("sys.version", "3.6") # needed to support [ use_embed=1 ] # indices for names and events (1..5) (B, C, D, E, F) = (1, 2, 3, 4, 5) (hurdles, long_jump, sprint, m1000, walk) = (1, 2, 3, 4, 5) # construct the MiniZinc model m = MiniZinc([ 'include "globals.mzn"', # scores for the competitors in each event: pts[event, competitor] = score "array [1..5, 1..5] of var 0..3: pts", # scores in each event are: 3, 2, 1, 0, 0 "constraint forall (i in 1..5) (sum (j in 1..5) (pts[i, j] = 3) = 1)", # 1st = 3pts "constraint forall (i in 1..5) (sum (j in 1..5) (pts[i, j] = 2) = 1)", # 2nd = 2pts "constraint forall (i in 1..5) (sum (j in 1..5) (pts[i, j] = 1) = 1)", # 3rd = 1pts "constraint forall (i in 1..5) (sum (j in 1..5) (pts[i, j] = 0) = 2)", # unplaced = 0pts # functions: "function var int: points(var int: j) = sum (i in 1..5) (pts[i, j])", "function var int: wins(var int: j) = sum (i in 1..5) (pts[i, j] = 3)", "function var int: scored(var int: j) = sum (i in 1..5) (pts[i, j] > 0)", # "the superchamp scored more points than anyone else" "var 1..5: S", "constraint forall (j in 1..5 where j != S) (points(j) < points(S))", # "the superchamp won more events than anyone else" "constraint forall (j in 1..5 where j != S) (wins(j) < wins(S))", # each competitor scored a different number of points "constraint all_different (j in 1..5) (points(j))", # each competitor scored in a different number of events "constraint all_different (j in 1..5) (scored(j))", # "B and C together scored twice as many points as F" "constraint points({B}) + points({C}) = 2 * points({F})", # "E was the only one to win his own event" # "and in that event the superchamp came second" "array [1..5] of var 1..5: spe", "constraint all_different(spe)", "constraint forall (j in 1..5) ((j == {E}) <-> (pts[spe[j], j] = 3))", "constraint pts[spe[{E}], S] = 2", # "in another event E gained 1 point less than the hurdler" "var 1..5: hurdler", "constraint spe[hurdler] = {hurdles}", "constraint exists (i in 1..5) (pts[i, {E}] + 1 = pts[i, hurdler])", # "the hurdler only came third in hurdles" "constraint pts[{hurdles}, hurdler] = 1", # "hurdles was won by D" "constraint pts[{hurdles}, {D}] = 3", # "D came last in long jump" "constraint pts[{long_jump}, {D}] = 0", # "D scored in the sprint" "constraint pts[{sprint}, {D}] > 0", # "F won the long jump" "constraint pts[{long_jump}, {F}] = 3", # "F was 2nd in the walk" "constraint pts[{walk}, {F}] = 2", # "F did not score in hurdles" "constraint pts[{hurdles}, {F}] = 0", # "B scored in the long jump" "constraint pts[{long_jump}, {B}] > 0", # "C scored in the sprint" "constraint pts[{sprint}, {C}] > 0", # "the 1000m man was 3rd in 2 events" "var 1..5: m1000er", "constraint spe[m1000er] = {m1000}", "constraint sum (i in 1..5) (pts[i, m1000er] = 1) = 2", # "the long jumper scored more points than the sprinter" "var 1..5: long_jumper", "constraint spe[long_jumper] = {long_jump}", "var 1..5: sprinter", "constraint spe[sprinter] = {sprint}", "constraint points(long_jumper) > points(sprinter)", ], use_embed=1) # map indices back to names / events (for output) name = {1: "Ben", 2: "Colin", 3: "Denis", 4: "Eddie", 5: "Fred"} event = {1: "hurdles", 2: "long jump", 3: "sprint", 4: "1000m", 5: "walk"} # solve the model and find: # pts = results in each event # spe = special event for each competitor for (pts, spe) in m.solve(solver="minizinc -a", result="pts spe"): # collect points t = dict((k, 0) for k in name.keys()) # output the results for each event for (i, rs) in enumerate(pts, start=1): (p1, p2, p3) = (rs.index(p) + 1 for p in (3, 2, 1)) printf("{e}: 1st = {p1}, 2nd = {p2}, 3rd = {p3}", e=event[i], p1=name[p1], p2=name[p2], p3=name[p3]) # collect points t[p1] += 3 t[p2] += 2 t[p3] += 1 printf() # determine superchamp S = max(t.keys(), key=t.get) assert all(k == S or v < t[S] for (k, v) in t.items()) # output the results for each competitor for j in sorted(event.keys()): printf("{j} [{e}]: {t} points{S}", j=name[j], e=event[spe[j - 1]], t=t[j], S=(' [SUPERCHAMP]' if j == S else '')) printf("--") printf()Solution: Denis is the long jumper. He scored 5 points.
The program finds 2 possible scenarios:
The solution published in the book (which runs to 3 pages) only gives the first of these solutions.
I think this is due to the interpretation of “In another event Eddie gained one point less than the hurdler”. The book solution seems to infer (hurdler = 3pts, Eddie = 2pts) or (hurdler = 2pts, Eddie = 1pt), and concludes it is not possible for C to be the champ.
And in the first scenario, in the long jump, we have: the hurdler (Ben) scores 2pts (2nd place), and Eddie scores 1pt (3rd place).
However, I think the wording also allows (hurdler = 1pt, Eddie = 0pts), and in the second scenario, in the long jump, we have: the hurdler (Colin) scores 1pt (3rd place), and Eddie scores 0pts (unplaced).
LikeLike
Frits 3:06 pm on 17 January 2026 Permalink |
from itertools import permutations ''' 3 2 1 hurdles A F K long J B G L sprint C H M super=Superchamp 1000m D I N Walk E J O ''' sports = [-1, -1, -1, -1, -1] (ben, colin, denis, eddie, fred) = range(5) dgts, sols = set(range(5)), set() A = denis # Denis won hurdles B = fred # Fred won the long jump J = fred # Fred was 2nd in the walk # Fred came nowhere in the hurdles for F, K in permutations(dgts - {A, fred}, 2): # hurdles # hurdler (K) came 3rd in the hurdles, Eddie is no hurdler if eddie == K: continue for G, L in permutations(dgts - {B, denis}, 2): # Denis last in long jump if 0 not in {G, L} : continue # Ben scored in long jump for C, H, M in permutations(dgts, 3): # sprint # Colin and Denis scored in the sprint if not {C, H, M}.issuperset({colin, denis}): continue for D, I, N in permutations(dgts, 3): # 1000m for E, O in permutations(dgts - {J}, 2): # walk gold = [A, B, C, D, E] silver = [F, G, H, I, J] bronze = [K, L, M, N, O] # Eddie was the only one to win his own special event if eddie not in gold: continue scores = [A, F, K, B, G, L, C, H, M, D, I, N, E, J, O] scored = [scores.count(i) for i in range(5)] # all scored in a different number of events. if len(set(scored)) != 5: continue pts = [sum([3 - (i % 3) for i, s in enumerate(scores) if s == j]) for j in range(5)] # all scored a different number of points if len(set(pts)) != 5: continue # Ben and Colin together scored twice as many points as Fred if pts[ben] + pts[colin] != 2 * pts[fred]: continue # the Superchamp won more events than anyone else ( >= 2) sups = sorted((f, i) for i in range(5) if (f := gold.count(i)) > 1) if not sups or (len(sups) == 2 and len(set(gold)) == 3): continue super = sups[-1][1] # once the Superchamp came 2nd after Eddie if super == eddie or super not in silver: continue # the Superchamp had the highest number of points if pts[super] != max(pts): continue sports[0] = K # hurdler only came third in the hurdles # check sports where Eddie and Superchamp ended 1 and 2 for e, (g, s) in enumerate(zip(gold, silver)): if (g, s) != (eddie, super): continue if e == 0: continue # Eddie is not the hurdler # in another event Eddie gained one point less than the hurdler for i, gsb in enumerate(zip(gold, silver, bronze)): if ((K, eddie) in zip(gsb, gsb[1:]) or (eddie not in gsb and gsb[-1] == K)): break else: # no break break sports_ = sports.copy() sports_[e] = eddie # Eddie performs sport <e> # assign people to remaining sports for p in permutations(dgts - {eddie, K}): sports__ = sports_.copy() j = 0 for i in range(5): if sports_[i] != -1: continue sports__[i] = p[j] j += 1 # Eddie was the only one to win his own special event for i, s in enumerate(sports__): if gold[i] == s and s != eddie: break else: # no break # the long jumper scored more points than the sprinter if not (pts[sports__[1]] > pts[sports__[2]]): continue # the thousand-metre man was third in two events if bronze.count(sports__[3]) != 2: continue # store solution sols.add((sports__[1], pts[sports__[1]])) names = "Ben Colin Denis Eddie Fred".split() print("answer:", ' or '.join(names[a] + ' with score ' + str(s) for a, s in sols))LikeLike