Chapter 167
Four Puzzles From Riddler Nation’s Students
To mark the 100th Riddler column, FiveThirtyEight handed the puzzles over to maths students. Four puzzles were posed: a handshake-arrangement count, a where-does-the-extra-digit-go riddle, an optional-skip standardised test, and an image-based cornucopia grid. The cornucopia (Riddle 4) depends on an image-only chart of leaves, pumpkins, apples, candy corn, and acorns whose pixel-level values are not recoverable from the corpus; it is deferred, consistent with the rest of this volume’s image-blocked puzzles. The three derivable puzzles follow.
Riddle 1
Six knights sit at a round table and must complete a greeting ceremony: every member shakes hands with every other member exactly once. During each round of handshakes, every member must be shaking exactly one hand, and arms may not cross. Between rounds, the seating may be rearranged. What is the minimum number of seating arrangements needed for six knights? Eight knights? knights?
The Riddler, FiveThirtyEight, November 17, 2017(original post)
Solution
The answer is arrangements, and must be even.
The non-crossing rule forces a bipartite cover. Each seating arrangement partitions the knights into two halves (those on the left of the table and those on the right). Within one arrangement, a single “round” of handshakes is a non-crossing perfect matching, but the problem allows many rounds in the same arrangement (no rearranging in between): we can keep handshaking until every left–right pair has shaken hands, since the chords between left and right knights can be enumerated in successive non-crossing matchings ( has a -factorisation). So one arrangement covers exactly the pairs that span its two halves.
A cover of the complete graph by complete bipartite subgraphs is what we need; the minimum number is the biclique cover number of . The Graham–Pollak theorem says this number equals .
The construction. Label the knights and view labels in binary. For , the th arrangement seats knights with bit equal to on the left and bit equal to on the right. Every pair of distinct knights differs in at least one bit, so each pair sits left–right in at least one arrangement and shakes hands then.
The lower bound. Pick any knight, call her . In one arrangement shakes hands with everyone on the opposite side, namely knights, so the count of knights she has not yet shaken with falls by at most a factor of two each arrangement (from to , etc.). She needs to reach , so the number of arrangements is at least .
For and : .
The computation
For each build the binary bipartition cover, enumerate every (left, right) pair within each arrangement, and check that every distinct has been covered.
For each arrangement , partition knights by bit of their label.
Within one arrangement, every (left, right) pair shakes hands at some point.
Aggregate across arrangements and confirm full pairwise coverage.
from math import ceil, log2
def covered_pairs(N):
R = ceil(log2(N))
pairs = set()
for r in range(R):
bit = 1 << r
L = [j for j in range(N) if (j & bit) == 0]
R_ = [j for j in range(N) if (j & bit) != 0]
for a in L:
for b in R_:
pairs.add(frozenset((a, b)))
return R, pairs
for N in (2, 4, 6, 8, 10, 12, 14, 16):
R, pairs = covered_pairs(N)
needed = N * (N - 1) // 2
print(N, "rounds =", R, "covers", len(pairs), "of", needed,
"ok =", len(pairs) == needed)
For every even in the sweep, the construction covers all pairs using exactly arrangements, matching the lower bound.
Riddle 2
In Kevin’s number system, the digit keleven (an integer that lies between two other single-digit integers) is inserted somewhere along the number line. Other than this insertion, all digits remain in the usual order. Two calculations found in Kevin’s notes: Where does keleven belong?
The Riddler, FiveThirtyEight, November 17, 2017(original post)
Solution
There are single-digit symbols (the usual ten plus keleven), so Kevin’s system is base-. Inserting keleven between digit symbols and (in the usual ordering) gives a digit ordering and the symbol-to-value map is: symbols keep their face values ; the symbol has value ; the symbols have values .
Test between and . Then the symbol-to-value map is , with unchanged.
The keleven string “853” has digit values , so as a base- number, “520” has digit values , so Their sum is . Convert to base-: . Digit values , which as keleven symbols are (since as a value writes as the symbol ). The base- representation is “.” Match.
Check the multiplication. “41” = ; “26” has digit values , so ; their product is . In base-, , digit values , which in keleven symbols are . The base- representation is “.” Match.
A short argument why this is the unique answer: the first equation gives in keleven, but the displayed result reads “,” i.e. a then a in the hundreds. So the hundreds-place sum, base-, equals ( carries) or . This rules out between and , narrowing to . The tens digit “” read against the keleven addition then forces between and .
The computation
Sweep ’s position from to ; check both equations for each candidate.
For each insertion point , build the symbol-to-value map.
Convert each keleven string to its base- value; compute sum and product.
Convert the answer back to base- digit values, then to keleven symbols.
The candidate is valid only if both equations round-trip.
def sym_to_val(s, d):
out = []
for c in s:
v = int(c)
out.append(v if v <= d else v + 1)
return out
def val_to_sym(vals, d):
out = []
for v in vals:
if v == d + 1:
out.append("K")
else:
out.append(str(v if v <= d else v - 1))
return "".join(out)
def kelven_to_int(s, d):
n = 0
for v in sym_to_val(s, d):
n = n * 11 + v
return n
def int_to_kelven(n, d):
if n == 0:
return "0"
vals = []
while n > 0:
vals.append(n % 11)
n //= 11
return val_to_sym(list(reversed(vals)), d)
for d in range(10):
add_lhs = kelven_to_int("853", d) + kelven_to_int("520", d)
mul_lhs = kelven_to_int("41", d) * kelven_to_int("26", d)
if int_to_kelven(add_lhs, d) == "1473" and \
int_to_kelven(mul_lhs, d) == "976":
print("K between", d, "and", d + 1) # 4 and 5
The sweep prints exactly one match: between and .
Riddle 3
A test (SAAD) has questions, each with two bubbles. Filling in the correct bubble for question gains points; filling in the incorrect bubble loses points. The student knows after each question whether it was right or wrong (before deciding the next). A student may also skip a question: skipping scores zero and resets the next question’s value back to . The second question is worth points (or , if the first was skipped), and so on. What strategy maximises the expected score?
The Riddler, FiveThirtyEight, November 17, 2017(original post)
Solution
Each question is a fair Bernoulli: filling in either bubble has a % chance of being right. The score on a non-skipped question is with equal probability, so its expected contribution is exactly . Skipping contributes . Whatever strategy you adopt, by linearity of expectation, No strategy can beat . The variance, however, depends sharply on the strategy: skipping everything yields a deterministic score of (variance ); answering all questions has variance . From the standpoint of a rational decision maker the deterministic-zero strategy is the one to pick: same expected value, no variance.
(The official Riddler answer puts the same conclusion more colourfully: “A strange game. The only winning move is not to play.”)
The computation
Simulate any strategy and confirm the empirical mean is zero to sampling precision; sweep over a small zoo of strategies (answer all; skip the high-value tail; alternating; skip-after-loss).
For each strategy, simulate one test by deciding (per question) to answer or skip and tossing a fair coin for correctness on answered questions.
Track running points: on a correct answer of current-value , on incorrect, on skip (and reset to ).
Average the final scores over many runs.
import random
def run_test(strategy, seed):
rng = random.Random(seed)
v, score = 1, 0
for q in range(100):
skip = strategy(q, v, score)
if skip:
v = 1
continue
win = rng.random() < 0.5
score += v if win else -v
v += 1
return score
def s_answer_all(q, v, s): return False
def s_skip_all(q, v, s): return True
def s_skip_after_loss(q, v, s):
return v > 1 and s < 0
for name, S in [("all", s_answer_all), ("skip", s_skip_all),
("after_loss", s_skip_after_loss)]:
N = 20_000
mean = sum(run_test(S, k) for k in range(N)) / N
print(name, "mean =", round(mean, 2)) # ~ 0
Every strategy averages close to zero; only skipping every question achieves it deterministically.