Chapter 160
Is Your Friend Full Of It?
Riddler Express
Your friend claims to have once made free throws in a row, having not touched a basketball for years. Assume he is a free-throw shooter. What is the expected number of free throws he would need to take before completing a streak of makes in a row? What if his accuracy were a little worse?
The Riddler, FiveThirtyEight, September 1, 2017(original post)
Solution
Let be the number of trials a Bernoulli() process needs to first produce a streak of consecutive successes. The expectation admits a clean closed form, Derivation. Condition on the first failure. Let . At any point before a success streak of length is achieved, restart the clock at any failure. Consider the first attempt: with probability it is a failure (one trial used, no progress), and with probability it is a success that begins a run. Continuing along a run of successes, if all shots in a row come up successes (probability ), we finish in trials; otherwise (probability ) the streak is broken at some point inside the first trials, and we restart fresh from the failure.
Working out the expectation with a first-step argument on each shot in the streak: The first term: with probability the first shots are all successes; we finish in trials. The summand: with probability the first shots are successes and the th is a failure (using trials), after which we start over with a fresh independent . Expanding, Move the term to the left, Use , which after simplification gives . Substituting and simplifying,
Plugging in , :
The estimate is highly sensitive to because the dominant term is , which grows like a geometric in when shrinks. At , , about times longer. The friend’s claim is plausible at accuracy (a couple of hours’ practice) but quickly becomes unreasonable as the shooting percentage drops.
The computation
Simulate the actual experiment: trial after trial of Bernoulli() shots, count the number of shots until the first run of length . Average over many trials.
Initialise streak length to , trial count to .
For each shot, increment trial count; flip a Bernoulli(); if heads, increment streak, else reset streak to .
Stop when streak reaches ; report trial count.
Average over many trials and compare to the closed form.
import random
def first_run(L, p, rng):
streak = n = 0
while streak < L:
n += 1
streak = streak + 1 if rng.random() < p else 0
return n
rng = random.Random(0)
trials = 30_000
mean = sum(first_run(17, 0.7, rng) for _ in range(trials)) / trials
print(round(mean, 1)) # ~1430
# closed form
p, L = 0.7, 17
print(round((1 - p**L) / ((1 - p) * p**L), 2)) # 1429.55
The empirical mean clusters around the closed form to within sampling error.
Riddler Classic
Seven players each receive a uniformly-random black or white hat. Each can see the others’ hats but not her own. Each player simultaneously and independently writes down “black”, “white”, or “pass”. The team wins if at least one player guesses her own hat colour correctly and nobody guesses wrong; otherwise the team loses. The players may agree on a strategy beforehand but cannot communicate during the game. What is the best winning probability? Extra credit: players.
The Riddler, FiveThirtyEight, September 1, 2017(original post)
Solution
The team can win with probability using a strategy built from the Hamming code. More generally, with players the team can win with probability .
The trick. Label the players with the nonzero binary strings of length : Anna , Ben , Clarice , Doug , Edna , Fred , Georgina . Each player , seeing the others’ hats, computes the bitwise XOR (i.e., addition modulo component-wise) of the labels of all teammates wearing a black hat. Call this value . The rule is:
If , guess “black”.
If equals the player’s own label, guess “white”.
Otherwise, pass.
Why it works. Let be the XOR of the labels of all black-hat wearers. Each player sees everyone else, so for :
If ’s hat is white, then (her own label contributes ).
If ’s hat is black, then (her label cancels out of the sum).
Player guesses black iff ; she guesses white iff .
Now consider the value of over a uniform random colouring of all seven hats:
Case . This means the XOR of all black labels is . Every player has XOR with or without her own label; specifically, if she has a black hat, if white. So every white-hat player guesses “black” and is wrong, and every black-hat player guesses “white” and is wrong. The team loses.
Case . Then , the binary string of some specific player. For this player : if her hat is black, , she guesses “black” correctly. If her hat is white, , she guesses “white” correctly. Either way, guesses correctly. Every other player has and , so passes. The team wins.
The team wins precisely when . Since the seven hats are i.i.d. uniform, is uniform over (any single hat colour, conditional on the others, makes equally likely to be any value), so .
Optimality. No strategy does better than . Consider the expected number of correct guesses minus wrong guesses across all colourings. Each individual player guesses correctly on exactly half the colourings she does not pass on (her own hat is independent of what she sees), so the per-player correct-minus-wrong total is zero. Summed across players, the total correct-minus-wrong is . Each colouring contributes either (one correct guess, others pass: team wins) or some negative quantity (any wrong guess: team loses); for the totals to sum to zero, the winning colourings exactly balance the wrong-guess contributions. The maximum is achieved when every winning colouring contributes exactly and every losing colouring contributes exactly (one wrong guess), with of colourings winning. This balance is achieved by the Hamming strategy.
Extra credit. With players, label players by the nonzero binary strings of length . The same XOR strategy applies, and the team wins iff the XOR of all black-hat labels is nonzero, which happens with probability .
The computation
Enumerate all hat colourings; for each, run the XOR strategy for each player; count the colourings in which the team wins.
For each player (binary labels ) and each colouring (a -bit string ):
Compute XOR of labels of teammates with .
If , guess black; if , guess white; else pass.
Team wins iff at least one guess is correct and no guess is wrong.
n = 7
labels = list(range(1, n + 1)) # 001..111 in binary
wins = 0
for b in range(1 << n):
hats = [(b >> i) & 1 for i in range(n)]
correct = wrong = 0
for p in range(n):
s = 0
for q in range(n):
if q != p and hats[q] == 1:
s ^= labels[q]
if s == 0:
guess = 1 # black
elif s == labels[p]:
guess = 0 # white
else:
guess = None
if guess is None:
continue
if guess == hats[p]: correct += 1
else: wrong += 1
if wrong == 0 and correct >= 1:
wins += 1
print(wins, wins / (1 << n)) # 112 0.875
The team wins on exactly of the colourings, confirming .