Brain-Teaser 668: Sweepstakes sixfold
From The Sunday Times, 28th April 1974 [link]
A party of six racegoers arrived on the course with precisely £6 each with which to speculate. There were six races on the card and six runners in each race, so they decided to hold sweepstakes among themselves on each of the six races, the stake being £1 per race per person.
The runners in each race were numbered 1, 2, 3, 4, 5 and 6, and each of the racegoers drew one of these numbers out of a hat. Each player’s number remained the same throughout the six races. There were thus, in effect, six separate sweepstakes, the holder of the winning number drawing £6 on each race. To add a little interest to the proceedings it was arranged that the winner on any one of the races would be permitted to buy (at cost price of £1) one additional chance in one or more of the races subsequent to his win, from one of the other players. Only a player who had not yet had a win could sell his chance.
At the conclusion of the events it transpired that three players had made a net profit; the holder of No. 1 who won £4, the holder of No. 5 who won £1, and the holder of No. 4. The holder of No. 2 lost £3, and the holder of No. 6 lost £6.
Three winning chances were sold, but none of these by the holders of Nos 1, 4 and 5. The holder of No. 1 did not have any transaction with the holders of Nos 2 and 3. There were no dead-heats and no number appeared in the winner’s frame in consecutive races.
What, in order, were the numbers of the six winning horses?
This puzzle is included in the book The Sunday Times Book of Brain-Teasers: Book 2 (1981). The puzzle text above is taken from the book.
[teaser668]

Jim Randell 9:40 am on 19 April 2022 Permalink |
At the start of the races each participant has a profit of −6 (having bought the 6 tickets with their own number on).
And in each race, the outcome for each participant is:
And there are some additional restrictions: a +5 or −1 can only come after a +6, and a +1 cannot come after a +6.
And we can use these facts to check that there is a sequence of viable outcomes for each participant (without this the following code takes a lot longer to run, but you can change
valid()to always returnTrueto try the slower version, but it will take a lot longer).This Python program looks for a viable sequence of winners and ticket transactions for each race. It runs in 4.28s.
Run: [ @replit ]
from enigma import (irange, subsets, product, diff, first, printf) # update a dictionary with given deltas def update(d, *kvs): d = d.copy() for (ks, v) in kvs: for k in ks: d[k] += v return d # find possible length k sequences that give total t def complete(k, t, f=0, ss=[]): xs = [[0, 1, 6], [-1, 0, 5, 6]][f] if k == 0: if t == 0: yield ss elif k == 1: if t in xs: yield ss + [t] else: # choose an outcome for x in xs: yield from complete(k - 1, t - x, f or (x == 6), ss + [x]) # is there a valid completion? valid = lambda k, t, f: bool(first(complete(k, t, f))) # totals we are given (also #3 not >0; #4 >0) totals = { 1: 4, 5: 1, 2: -3, 6: -6 } # solve the puzzle # n = remaining races # vs = ticket values # m = money for each participant # ws = winning tickets for each race # ps = winning players for each race # bs = potential buyers def solve(n, vs, m, ws=list(), ps=list(), bs=set()): if n == 0: # check totals if not (m[4] > 0 and not (m[3] > 0) and all(m[k] == v for (k, v) in totals.items())): return # check three winning tickets were sold if not (sum(x != y for (x, y) in zip(ws, ps)) == 3): return # viable solution yield (m, ws, ps) else: # choose some buyers and sellers b = len(bs) for k in irange(0, min(b, 6 - b)): for (bs1, ss1) in product(subsets(bs, size=k), subsets(diff(vs, bs), size=k, select="P")): # determine who gets the winnings d = dict(zip(ss1, bs1)) # but 1 did not have any transactions with 2 or 3 if any(d.get(k, 0) == v for (k, v) in [(1, 2), (1, 3), (2, 1), (3, 1)]): continue # perform the transactions m1 = update(m, (bs1, -1), (ss1, +1)) # at this point we can check the targets of any sellers are reachable if any(not valid(n - 1, totals[k] - m1[k], k in bs) for k in ss1 if k in totals): continue # choose a winner for the race for w in vs: # no consecutive winners if ws and ws[-1] == w: continue # has the winning ticket been sold? p = d.get(w, w) if p != w: # winning ticket was sold, but not by 1, 4, 5 if w in {1, 4, 5}: continue # and only 3 winning tickets were solve if sum(x != y for (x, y) in zip(ws, ps)) > 2: continue # allocate the winnings m_ = update(m1, ([p], +6)) bs_ = bs.union([p]) # check all (non-seller) targets are reachable if any(not valid(n - 1, v - m_[k], k in bs_) for (k, v) in totals.items() if k not in ss1): continue # solve for the remaining races yield from solve(n - 1, vs, m_, ws + [w], ps + [p], bs_) # initial values vs = list(irange(1, 6)) # available tickets m = dict((k, -6) for k in vs) # initial amounts for (m, ws, ps) in solve(6, vs, m): printf("winning tickets = {ws}; profits = {m}", m=list(m[i] for i in vs))Solution: The numbers of the winning horses were: 5, 4, 2, 3, 2, 1.
One scenario is:
There are alternative scenarios, in each we have (#3, #4) → (−4, +8) or (−5, +9).
But in each scenario the winning tickets are (5, 4, 2, 3, 2, 1).
LikeLike