Teaser 2582: Anyone for tennis?
From The Sunday Times, 18th March 2012 [link] [link]
The girls of St Trinian’s choose two games from the four on offer. In Felicity’s gang of four, no game was chosen by both Daphne and Erica; Chloe and Miss Brown chose lacrosse; Miss Smith chose netball; and only Miss Jones excluded hockey. In Harriet’s gang of four, Clara, Debbie and Ellen all chose netball but only one of the four chose hockey. To avoid having two girls with the same first name initial in any one game, one of the girls in the second group (but not Debbie) moved from one game to another. This meant that there was an odd number of these [eight] girls playing each game.
Which of the eight girls played tennis?
[teaser2582]





Jim Randell 10:42 am on 28 January 2025 Permalink |
We want each of the sports to end up with an odd number of participants after the swap.
So before the swap there must be two sports that have an even number of participants (and the other two sports have an odd number of participants). And the swap must occur from one of the sports with an even number of participants to the other sport with an even number of participants. Leaving all sports with an odd number.
Furthermore, the girl who swaps (who is in the second group, and shares and initial with a member of the first group, and is not Debbie – so must be Clara or Ellen), must have chosen one of the even sports (that was also chosen by her counterpart with the same initial), and not chosen the other even sport (that was also not chosen by her counterpart with the same initial, otherwise the swap would not remedy the situation). And this must be the only situation where a sport has been chosen by two girls with the same initial.
This Python program uses the [[
SubstitutedExpression()]] solver from the enigma.py library to determine possible choices for each of the groups separately, and then combines possibilities to consider possible choices for the 8 girls, and then checks the remaining conditions for the combined choices.It runs in 82ms. (Internal runtime is 11.5ms).
from enigma import ( SubstitutedExpression, cproduct, chain, filter2, multiset, singleton, diff, join, printf ) # possible choices are: # # k L N H T # 0 = - - x x (HT) # 5 = x x - - (LN) # 1 = - x - x (NT) # 4 = x - x - (LH) # 2 = - x x - (NH) # 3 = x - - x (LT) # # such that for a choice k the unchosen options are (5 - k) # map choice numbers to sports (0 - 5) choice = ['HT', 'NT', 'NH', 'LT', 'LH', 'LN'] # sets for the four sports macros = { 'lacrosse': "{3, 4, 5}", 'netball': "{1, 2, 5}", 'hockey': "{0, 2, 4}", 'tennis': "{0, 1, 3}", } # group 1: # for sport choices allocate: C, D, E, F to k-values (0-5) # for surnames allocate: B, S, J to values 0-3 (= C - F) [distinct] exprs1 = [ # "no game was chosen by both D and E" "D + E == 5", # "C chose lacrosse" "C in @lacrosse", # "Miss Brown (who is not C) also chose lacrosse" "B != 0", "[C, D, E, F][B] in @lacrosse", # "Miss Smith chose netball" "[C, D, E, F][S] in @netball", # only Miss Jones excluded hockey "all((x in @hockey) == (i != J) for (i, x) in enumerate([C, D, E, F]))", ] names1 = "Chloe Daphne Erica Felicity".split() surnames1 = "Brown Smith Jones".split() def solve1(): # find the first group p1 = SubstitutedExpression( exprs1, base=6, macro=macros, distinct="BSJ", d2i={ 4: "BSJ", 5: "BSJ" }, ) for s in p1.solve(verbose=0): # map names to choices d1 = dict((x, choice[s[x[0]]]) for x in names1) # map names to surnames sn = dict((names1[s[x[0]]], x) for x in surnames1) yield (d1, sn) # group 2: # for sport choices allocate: C, D, E, H to k-values (0-5) exprs2 = [ # "C, D, E all chose netball" "{C, D, E}.issubset(@netball)", # "only one of C, D, E, H chose hockey" "sum(x in @hockey for x in [C, D, E, H]) == 1", ] names2 = "Clara Debbie Ellen Harriet".split() def solve2(): # find the second group p2 = SubstitutedExpression(exprs2, base=6, macro=macros, distinct="") for s in p2.solve(verbose=0): # map names to choices d2 = dict((x, choice[s[x[0]]]) for x in names2) yield d2 # output a group def output(g, sn=None): for k in sorted(g.keys()): s = (sn.get(k) if sn else None) name = (k + " " + s if s else k) printf("{name} -> {v}", v=join(g[k], sep=' + ')) printf() # choose solutions for each group for ((g1, sn), g2) in cproduct([solve1(), solve2()]): # make the combined solution g = dict(chain(g1.items(), g2.items())) # map each sport to a list of girls s = dict((k, list()) for k in 'LNHT') for (k, vs) in g.items(): for v in vs: s[v].append(k) # find sports with even and odd numbers of participants (even, odd) = filter2((lambda k: len(s[k]) % 2 == 0), s.keys()) # there must be 2 even sports if len(even) != 2: continue # find sports that have more than one participant with a given initial ms = list() for (k, vs) in s.items(): ds = list(x for (x, n) in multiset.from_seq(v[0] for v in vs).items() if n > 1) if ds: ms.append((k, ds)) # there must be just one sport with just one duplicated initial if not (len(ms) == 1 and len(ms[0][1]) == 1): continue (x, i) = (ms[0][0], ms[0][1][0]) # the duplicate sport must have an even number of participants # and we must swap to the other sport with an even number of participants y = singleton(diff(even, {x})) if y is None: continue # the duplicate initial must be C or E swap = other = None if i == 'C': # Clara needs to swap from x to y (swap, other) = ('Clara', 'Chloe') elif i == 'E': # Ellen needs to swap from x to y (swap, other) = ('Ellen', 'Erica') # check the swap fixes the issue if swap is None or not (x in g[swap] and y not in g[swap] and y not in g[other]): continue # final list for tennis ts = list(s['T']) if x == 'T': ts.remove(swap) if y == 'T': ts.append(swap) # output solution: # first output the choices for each group output(g1, sn) output(g2) # output the swap, and the final list for tennis printf("{swap} swaps {x} -> {y}") printf("-> tennis = {ts}", ts=join(ts, sep=", ", sort=1)) printf()Solution: The girls playing tennis are: Clara, Debbie, Erica.
The initial choices made are:
But both Erica and Ellen have chosen netball, so there would be 2 girls with the same initial in the netball group.
To fix this Ellen swaps from netball to hockey, giving the following assignments:
LikeLike