Teaser 2182: Team bonding
From The Sunday Times, 11th July 2004 [link]
The 21 members of the football club’s squad (who wear shirts numbered from 1 to 21) were asked to turn up for training. But some missed the session because of injuries. The club trainer asked the players present to stand in a circle so that, for any adjacent pair of players, one of their numbers was a multiple of the other. The trainer, a keen puzzler, took this opportunity because he realised that this was the largest number of players from the squad for whom the exercise could work.
After a little effort, the players arranged themselves as requested. One player noticed that the sum of his two neighbours’ numbers equalled the lowest of the injured players numbers, and (a little further around the circle in a clockwise direction) another player noticed the sum of his two neighbours’ numbers equalled the highest of the injured players’ numbers. In no case did a player’s two neighbours add up to 20.
Starting at 1, list the order of the players clockwise around the circle.
[teaser2182]








Jim Randell 8:30 am on 23 May 2023 Permalink |
This Python program generates possible maximal length chains where in each pair of adjacent numbers, one is a multiple of the other. We start the chain with 1, so we know it can form a circle.
We then look for chains that satisfy the remaining conditions.
It runs in 220ms. (Internal runtime is 120ms).
Run: [ @replit ]
from enigma import (Accumulator, irange, diff, tuples, printf) ordered = lambda x, y: (x, y) if x < y else (y, x) # generate possible chains, such that for each pair of adjacent # numbers one is a multiple of the other def generate(ss, rs): yield ss for n in rs: (a, b) = ordered(ss[-1], n) if b % a == 0: yield from generate(ss + [n], rs.difference([n])) # start with 1 and solve for the remaining numbers r = Accumulator(fn=max, collect=1) for ss in generate([1], set(irange(2, 21))): r.accumulate_data(len(ss), ss) # find position whose neighbours satisfy fns def find(ss, fns): n = len(ss) d = dict(enumerate(fns)) r = [None] * len(fns) for (i, (x, y, z)) in enumerate(tuples(ss, 3, circular=1)): for (k, fn) in list(d.items()): if fn(x, z): r[k] = (i + 1) % n del d[k] if not d: break return r # consider maximal arrangements for ss in r.data: # find the missing numbers xs = diff(irange(1, 20), ss) # look for positions where the neighbours are: # i = equal to the smallest missing number # j = equal to the largest missing number # k = equal to 20 fn = lambda z: (lambda x, y, z=z: x + y == z) (i, j, k) = find(ss, [fn(xs[0]), fn(xs[-1]), fn(20)]) if i is None or j is None or k is not None: continue # calculate clockwise distance: i -> j n = len(ss) d = (j - i) % n if 2 * d > n: continue # output solution printf("{ss} (i={i} j={j})")Solution: 1, 9, 18, 6, 12, 4, 16, 8, 2, 14, 7, 21, 3, 15, 5, 10, 20.
The missing numbers are: 11, 13, 17, 19.
And Player 20 has neighbours that sum to 11 (= 10 + 1). Player 9 has neighbours that sum 19 (= 1 + 18). No-one has neighbours that sum to 20.
LikeLike