Teaser 3344: Wining and dying
From The Sunday Times, 25th October 2026 [link] [link]
You are a king with 15 wine barrels in your cellar. You know that exactly one of the barrels contains a lethal poison, but you do not know which. On day one you give some wine (or none) to each of your four wine tasters. Any who took poison will be dead by the next day. The trouble is that you cannot tell the tasters apart, so if any of them do die you cannot be certain what wine it was you gave them. On day two you observe how many are still alive and can repeat the process with them, carrying on until you have identified the poisoned barrel.
On which day can you be absolutely certain which is the poisoned wine?
[teaser3344]








Jim Randell 6:22 am on 25 October 2026 Permalink |
If we cannot distinguish the tasters, then the outcome of a tasting is how many of the tasters survive. So with 4 tasters the possible outcomes are that 0, 1, 2, 3, 4 of them survive, which is only 5 possible outcomes. And there are 15 barrels, so we are going to need more than 1 round of tastings.
Let B(k, r) be the maximum number of barrels that can be resolved given k tasters and r rounds of tasting.
In 0 rounds we can only determine the poison barrel if there is only 1 barrel to choose from.
In 1 round of tasting there can be (k + 1) different outcomes (i.e. 0 .. k of the tasters die). So, if we label the barrels 0 .. k, and have the same number of tasters taste each barrel as the number on the label, then we can determine the poison barrel directly from the number of tasters that die.
For r > 1 we can have groups of barrels that are tasted by 0 .. k of the tasters, and the number of barrels that we allocate to each group must be the number that can be resolved by the surviving tasters (who were not part of that group).
This gives a straightforward recursive implementation of B(k, r).
This Python program looks at increasing numbers of rounds with 4 tasters, until we are able to resolve 15 barrels.
from enigma import (irange, inf, cache, arg, printf) # B(k, r) = max number of barrels that can be resolved # with <r> rounds of tasting and <k> tasters (initially) @cache def B(k, r): # in 0 rounds we can resolve 1 barrel if r == 0: return 1 # in 1 round we can resolve (k + 1) barrels if r == 1: return k + 1 # otherwise allocate barrels to tasters according to how many # barrels can be resolved by j surviving tasters in (r - 1) rounds return sum(B(j, r - 1) for j in irange(0, k)) n = arg(15, 0, int, prompt="number of barrels") k = arg(4, 1, int, prompt="number of tasters") # find minimum number of rounds to resolve <n> barrels for r in irange(0, inf): b = B(k, r) printf("[B({k}, {r}) = {b}]") if b >= n: printf("{n} barrels, {k} tasters -> {r} rounds") breakSolution: [To Be Revealed]
[Details – To Be Revealed]
See also: Teaser 2784.
LikeLike