Chapter 224
How Many Earthlings Would Survive 63 Thanos Snaps?
Riddler Express
Thanos, the all-powerful supervillain, can snap his fingers and destroy half of all the beings in the universe. What if there were Thanoses, each snapping his fingers one after the other? Out of billion people on Earth, how many can we expect to survive? If there were Thanoses, what would the survival fraction be?
The Riddler, FiveThirtyEight, April 26, 2019(original post)
Solution
The wording matters. A snap destroys “half of all the beings in the universe,” and the other Thanoses are beings too. So each snap halves both the human population and the surviving Thanoses, which means later Thanoses may never get to snap. That is what makes the answer interesting.
Setup. Each surviving being (human or Thanos) survives an individual snap independently with probability . Let be the expected fraction of humans who survive when the queue starts with Thanoses. The first Thanos snaps; every human survives with probability , so the population is multiplied by in expectation. After that snap, the remaining Thanoses have been thinned by independent fair coins, so the number of surviving Thanoses is , and what happens next is an independent instance of the same problem with Thanoses.
Recursion. By the tower property, The outer is the first Thanos’s halving of humans; the sum averages over the random number of Thanoses left.
Small cases. Notice how and : the extra Thanoses sometimes destroy each other before they can act, so the population fares better than the naive “halve times” guess of .
The naive number is wrong. Counting the modal number of snaps before the queue runs out (start with ; the surviving count typically halves: , about snaps) gives the population fraction , or about million survivors. That ignores the spread of . With the correct conditioning, , so the expected number of survivors is
The computation
Re-encode the problem itself, not the recursion. Simulate the queue of Thanoses one snap at a time, with each surviving being (population unit and remaining Thanos) independently halved. The empirical fraction over many trials must match to Monte Carlo precision, and an independent exact pass via the recursion must produce the same number.
Track the queue of remaining Thanoses and one population variable, here a count of “population atoms” for low-variance counting.
Pop the front Thanos; halve each surviving being independently by a draw.
Stop when the queue is empty; record the fraction of population atoms that survived.
Average across trials at ; compare to the exact from the recursion.
import random
from fractions import Fraction
from math import comb
def simulate(N, pop=1_000_000):
thanoses = N
alive = pop
while thanoses >= 1:
thanoses -= 1
survivors_thanos = sum(1 for _ in range(thanoses) if random.random() < 0.5)
thanoses = survivors_thanos
# halve population by independent coin flips, via binomial
# equivalent to: alive = Binomial(alive, 1/2)
# use sum of independent halvings; for large alive use binomial sample
alive = sum(1 for _ in range(alive) if random.random() < 0.5) \
if alive < 200 else \
_binomial_half(alive)
return alive / pop
def _binomial_half(n):
# sample Binomial(n, 1/2) via normal approx for large n
import math
mu = n / 2
sd = math.sqrt(n / 4)
return max(0, min(n, int(round(random.gauss(mu, sd)))))
def exact_f(N_max):
f = {0: Fraction(1)}
for N in range(1, N_max + 1):
s = Fraction(0)
for k in range(N):
s += Fraction(comb(N - 1, k), 2 ** (N - 1)) * f[k]
f[N] = Fraction(1, 2) * s
return f
random.seed(2019)
N = 63
trials = 50_000
emp = sum(simulate(N) for _ in range(trials)) / trials
exact = exact_f(N)[N]
print(f"empirical f({N}) = {emp:.6f}")
print(f"exact f({N}) = {float(exact):.6f}")
print(f"expected survivors out of 7.5e9 = {7.5e9 * float(exact):,.0f}")
print()
for N in [1, 2, 3, 5, 10, 20, 63]:
print(f"f({N:2d}) = {float(exact_f(N)[N]):.8f}")
The script prints empirical matching the exact , and a survivor count of about , reproducing the boxed million.
Riddler Classic
You and three friends are contestants on the newest edition of “Guess Your Hat.” Each of you has a hat placed on your head, one of four colors: red, yellow, blue, or green. Two of you might have the same colour. You can see everyone else’s hat but not your own, and your goal is to guess your own colour. You can’t communicate during the game but you can agree a strategy beforehand. The showrunners hear that strategy and choose the hats in the worst possible way for you. Can you guarantee that at least one of you wins? At least two?
The Riddler, FiveThirtyEight, April 26, 2019(original post)
Solution
The key move is to label the four colours by the integers and work modulo . The sum of all four hat-labels is some value (mod ). If everyone could agree in advance to “cover” each possible value of , exactly one player would always be right.
The strategy. Assign each friend an integer . Friend sees the other three hats summing to and guesses the colour Friend is correct iff the actual sum of all four hats is , because their guess plus the visible sum equals .
For any choice of hats, the true sum is one specific value, so exactly one friend is correct. The showrunners cannot prevent that: whatever they pick, is something, and the matching friend wins.
Why two cannot be guaranteed. Count winners across all configurations under any deterministic strategy. Friend ’s guess depends only on the three hats they see, so under a uniform random assignment of hats their own hat is independent of and matches it with probability exactly . Summing over the four friends, the expected number of winners under uniform random hats is If some strategy guaranteed winners on every configuration, the expectation under any distribution would be at least , contradicting the value above. So there is a configuration with at most winner, and an adversary will pick it.
The argument generalises: with players and colours, labelling colours and letting friend guess guarantees exactly winner under adversarial play, and the same uniform-expectation argument forbids .
The computation
Verify both claims exhaustively. For the four-friend, four-colour version there are configurations. The modulo- strategy must yield at least one winner in every one of them, and there must be no four-friend deterministic strategy that yields at least two winners in every configuration.
Enumerate all hat assignments.
For each, count how many of the four friends guess correctly under the modulo- strategy. Check that the minimum across configurations is and the maximum is (it is exactly , by construction).
For the impossibility, exploit linearity: under uniform random hats, for any deterministic strategy. So , hence . Verify on the mod- strategy and on a few other concrete strategies.
from itertools import product
COLOURS = 4
PLAYERS = 4
def mod4_guess(i, others):
# others is a tuple of the three hats friend i can see
s = sum(others) % COLOURS
return (i - s) % COLOURS
def count_winners(hats, strategy):
n = 0
for i in range(PLAYERS):
others = tuple(hats[j] for j in range(PLAYERS) if j != i)
if strategy(i, others) == hats[i]:
n += 1
return n
configs = list(product(range(COLOURS), repeat=PLAYERS))
winners = [count_winners(h, mod4_guess) for h in configs]
print(f"configs = {len(configs)}")
print(f"min winners = {min(winners)}")
print(f"max winners = {max(winners)}")
print(f"avg winners = {sum(winners)/len(winners):.4f}")
# Try a naive "always guess 0" strategy.
naive = lambda i, others: 0
nw = [count_winners(h, naive) for h in configs]
print(f"naive min/avg = {min(nw)}/{sum(nw)/len(nw):.4f}")
The script prints for the modulo- strategy across all configurations, average , and the naive “always guess ” has minimum and average as expected.