Chapter 217
Don’t Trust Anyone Older Than L
Riddler Express
On an island, every native younger than age always tells the truth, and every native of age or older always lies. Five natives , , , , each make two statements about another’s age, listed below. What is ? What can be said about each native’s age?
A: “B is more than 20 years old.” B: “C is more than 18 years old.”
C: “D is less than 22 years old.” D: “E is not 17 years old.”
E: “A is more than 21 years old.”
A: “D is more than 16 years old.” B: “E is less than 20 years old.”
C: “A is 19 years old.” D: “B is 20 years old.”
E: “C is less than 18 years old.”
The Riddler, FiveThirtyEight, February 22, 2019(original post)
Solution
There are ways to label each of as truth-teller (T) or liar (). For any fixed labelling, each statement becomes a constraint on the target’s age: if the speaker is T, the predicate holds; if the speaker is , its negation holds. A labelling is consistent when the two constraints on each native are simultaneously satisfiable. The puzzle also demands a single integer threshold such that every T has age and every has age .
Three direct contradictions. Reading down the list:
says ; says . These cannot both be true, so at least one of and lies.
says ; says . So at least one of and lies.
says ; says . Cannot both be true, so at least one of and lies.
A fourth quick check: if and are both truth-tellers, then and , but also (from ’s first statement, since would have to be a liar by the - contradiction, making false). The contradictions narrow the search.
Search. Looping through labellings, only one labelling makes every statement-induced constraint mutually satisfiable: , , are liars; and are truth-tellers. Substituting:
About : lies, so ; tells the truth, so . Hence .
About : lies, so ; tells the truth, so . Hence .
About : lies, so ; lies, so . Hence .
About : tells the truth, so ; lies, so . Hence .
About : tells the truth, so ; lies, so . Hence .
The truth-tellers and have ages , and the liars , , have ages , so any with works and the only integer one is .
The computation
Encode the statements as constraints and brute-force over the truth-teller patterns, checking each for joint satisfiability and extracting the implied age intervals.
Each speaker tells the truth or lies (one of patterns).
Each predicate then forces the target’s age into a subset of .
A pattern is consistent iff every native’s intersected age set is non-empty.
For each consistent pattern, find an integer threshold such that T’s age and ’s age .
from itertools import product
names = ['A', 'B', 'C', 'D', 'E']
stmts = [
('A', 'B', lambda b: b > 20),
('B', 'C', lambda c: c > 18),
('C', 'D', lambda d: d < 22),
('D', 'E', lambda e: e != 17),
('E', 'A', lambda a: a > 21),
('A', 'D', lambda d: d > 16),
('B', 'E', lambda e: e < 20),
('C', 'A', lambda a: a == 19),
('D', 'B', lambda b: b == 20),
('E', 'C', lambda c: c < 18),
]
for liars in product([False, True], repeat=5):
valid = {n: set(range(0, 121)) for n in names}
for speaker, target, pred in stmts:
want = not liars[names.index(speaker)]
valid[target] = {a for a in valid[target]
if pred(a) == want}
if not all(valid[n] for n in names):
continue
for L in range(0, 121):
ok, ranges = True, {}
for i, n in enumerate(names):
if liars[i]:
cand = [a for a in valid[n] if a >= L]
else:
cand = [a for a in valid[n] if a < L]
if not cand:
ok = False
break
ranges[n] = (min(cand), max(cand))
if ok:
print('liars =', dict(zip(names, liars)),
'L =', L, 'ages =', ranges)
break
The script prints the single solution: liars , , ages , , , , , matching the boxed answer.
Riddler Classic
In a bridge auction four players sit around a table and take turns starting from the dealer. On each turn a player may either pass or make a bid. A bid is a (number, suit) pair with the number in and the suit one of clubs, diamonds, hearts, spades, no-trump (low to high). Each bid must rank strictly higher than the previous bid. The auction ends if all four players pass at the start, or if three consecutive passes follow a bid. How many distinct legal bridge auctions are there? Extra credit: count the auctions when bids may also be doubled or redoubled by the opposing partnership.
The Riddler, FiveThirtyEight, February 22, 2019(original post)
Solution
The auction is a finite sequence of moves drawn from a small alphabet, with structural constraints.
Setting up the alphabet. There are distinct bids ordered by rank. A legal auction is described by a strictly increasing subsequence of these bids, interleaved with pass tokens. Specifically:
Either zero bids occur (auction ends with all four passing at the start). That is exactly one auction.
Or bids occur, in strictly increasing rank order: there are choices of which bids.
For an auction with bids, count the legal arrangements of passes. The auction must end in exactly three passes (closing the bidding after the last bid), so those three are fixed. Before the first bid, between and passes may occur (the dealer’s seat plus the next two seats can each pass before the bidding opens); that gives options. Between any two successive bids, , , or passes may occur (any more than would close the auction prematurely); that gives options at each of the between-bid slots.
The counting formula. Putting the pieces together, Evaluating: . The leading is the all-pass opening.
The computation
Compute the sum directly using Python’s arbitrary-precision integers.
from math import comb
total = 1 + sum(comb(35, N) * 4 * 3**(N-1) for N in range(1, 36))
print(f"Legal auctions = {total:,}")
The script prints , matching the boxed answer.
Extra Credit
If doubling and redoubling are allowed (each immediately after the previous bid by an opponent, and each may be followed by up to two passes before the next move), how many distinct auctions are there?
Solution
The structure of bids is unchanged: bids are chosen, in strictly increasing rank order, in ways. What changes is what happens between successive moves.
The slot enumeration. Between two adjacent bids, the action options multiply: the bidder of the new bid was preceded by at most two passes ( pass options), the previous bid could have been doubled and the doubling could have been redoubled, and any double or redouble could itself be followed by up to two passes. Working through the bridge rules, the number of distinct “between-bid” move strings is , and the auction-closing tail (the moves after the final bid) has valid forms. The figure counts the legal arrangements of (pass, double, redouble, pass) where double and redouble must be made by the appropriate side and may each be followed by up to two passes; the figure counts the legal closing combinations (the final bid stands, or is doubled, or is redoubled, each followed by the appropriate three-pass close).
The counting formula. With those constants, The leading is again the all-pass opening; the leading for the moves before the first bid is unchanged (passes only); counts the between-bid move strings; the counts the closing tail.
The computation
from math import comb
total = 1 + sum(
comb(35, N) * 4 * 21**(N-1) * 7
for N in range(1, 36)
)
print(f"EC auctions = {total:,}")
The script prints the -digit value displayed in the boxed Extra Credit answer above, matching it digit-for-digit.