Chapter 284
Can You Feed The Hot Hand?
The Riddler for October 23, 2020. The Express exposes the famous “hot hand” selection bias in a short sequence of shots, and the Classic balances a one-on-one basketball game with rebounds and steals.
Riddler Express
Sue Bird makes every shot with probability exactly , independent of history. In each trial she takes three shots. Stewart keeps only the trials containing at least one shot that was immediately preceded by a made shot, picks one such trial at random, then picks at random one of its shots that was immediately preceded by a made shot. What is the probability that the chosen shot was made?
The Riddler, FiveThirtyEight, October 23, 2020(original post)
Solution
It is not . The eight equally likely sequences (X = made, O = missed) are OOO, OOX, OXO, XOO, OXX, XOX, XXO, XXX. The two without any shot following a made shot (OOO, OOX) are discarded, leaving six, each chosen with probability . Within a trial, look at the shots immediately preceded by a made shot and record the fraction of them that were made: Averaging these per-trial fractions (Stewart picks a trial first, then a shot within it), The selection rule is biased toward misses: conditioning on “the previous shot was made” and then sampling shots makes a made shot look less than likely. This is the Miller–Sanjurjo bias behind the hot-hand fallacy.
The computation
Encode the procedure: enumerate the eight sequences, and for each keep the shots preceded by a make, recording the made-fraction; average over the qualifying trials.
import itertools
from fractions import Fraction
fractions = []
for seq in itertools.product('XO', repeat=3):
after_make = [i for i in range(1, 3) if seq[i - 1] == 'X']
if not after_make:
continue # no qualifying shot: discard trial
made = sum(1 for i in after_make if seq[i] == 'X')
fractions.append(Fraction(made, len(after_make)))
print(sum(fractions) / len(fractions)) # 5/12
Averaging the per-trial made-fractions gives , below one half.
Riddler Classic
LeBron and Davis play sudden-death one-on-one; a coin decides first possession, and the first basket wins. Each makes a shot with probability . Davis rebounds every miss (his or LeBron’s) and resets to the three-point line. Before each of Davis’s shots, LeBron steals with probability , regaining possession. For what is the game even?
The Riddler, FiveThirtyEight, October 23, 2020(original post)
Solution
Let be LeBron’s win probability when he has the ball and his win probability when Davis has it. When LeBron has possession he either scores () or misses (); a miss is rebounded by Davis, so When Davis has possession, LeBron either steals (probability , moving to state ) or fails to steal (), after which Davis must miss () for LeBron to get another chance (back to state ): The coin makes LeBron’s overall win probability , and fairness requires it to equal , i.e. . From and we get , . Substituting into the middle equation, LeBron needs to steal a third of the time to offset Davis’s monopoly on rebounds.
The computation
Encode the three equations (, , and the fairness condition ) and solve for ; cross-check with a direct simulation.
import sympy as sp
J, D, p = sp.symbols('J D p')
sol = sp.solve([J - (sp.Rational(1, 2) + D / 2),
D - (p * J + (1 - p) * D / 2),
J + D - 1], [J, D, p], dict=True)[0]
print(sol[p], sol[J], sol[D]) # 1/3 2/3 1/3
import random
def lebron_wins(pp, rng):
davis_ball = rng.random() < 0.5 # who starts
while True:
if not davis_ball: # LeBron shoots
if rng.random() < 0.5: return True
davis_ball = True # miss -> Davis rebounds
else: # Davis has the ball
if rng.random() < pp: # LeBron steals
davis_ball = False; continue
if rng.random() < 0.5: return False # Davis scores
# Davis misses -> he rebounds, still his ball
rng = random.Random(0); n = 400_000
print(round(sum(lebron_wins(1/3, rng) for _ in range(n)) / n, 3)) # ~0.5
Solving gives , and the simulation confirms a coin-flip game at that steal rate.