Library · The Riddler · Chapter 260

Can You Catch The Free T-Shirt?

Revised Report an error

The Riddler for April 10, 2020. The Express launches T-shirts from a cannon at a random angle and asks which row is the safest bet to catch one. The Classic watches spam comments breed replies and asks how many posts pile up in three days.

Riddler Express

A T-shirt cannon in front of Row 11 can just reach the back of Row 100100 (no farther), with no air resistance. The launch angle is uniform between 0∘0^\circ (flat) and 90∘90^\circ (straight up). Which row should you sit in to maximise your chance of catching the shirt?

The Riddler, FiveThirtyEight, April 10, 2020(original post)

Solution

A projectile launched at angle θ\theta travels a horizontal distance proportional to sin⁡2θ\sin 2\theta, and the maximum range (at θ=45∘\theta = 45^\circ) reaches the back of Row 100100. Measuring distance in rows, the shirt lands at R(θ)=100 sin⁡2θ.R(\theta) = 100\,\sin 2\theta . As θ\theta sweeps uniformly from 0∘0^\circ to 90∘90^\circ, the landing row RR runs from 00 up to 100100 and back to 00. The chance of landing in a given row is governed by how fast RR changes with θ\theta: where RR changes slowly, many angles funnel the shirt into the same row. Since dRdθ=200cos⁡2θ\tfrac{dR}{d\theta} = 200\cos 2\theta vanishes at θ=45∘\theta = 45^\circ, the curve is flattest at its peak, so a wide band of angles all land near the maximum. The most likely landing row is therefore the very back, Row 100,\boxed{\text{Row } 100}, caught about 9%9\% of the time. (This is the same reason a rainbow is bright at its maximum-deflection angle: probability piles up where the mapping is flat.)

The computation

Encode the launch: draw angles uniformly, send each shirt to row ⌈100sin⁡2θ⌉\lceil 100\sin 2\theta\rceil, and tally which row catches the most.

import numpy as np, math
from collections import Counter
th = np.random.default_rng(0).uniform(0, math.pi/2, 20_000_000)
rows = np.clip(np.ceil(100*np.sin(2*th)).astype(int), 1, 100)
cnt = Counter(rows.tolist())
best = max(range(1, 101), key=lambda r: cnt[r])
print(best, round(cnt[best]/len(th), 3))     # 100 0.09

Row 100100 catches the most shirts, about 9%9\% of launches, as boxed.

Riddler Classic

Spam comments arrive on the column as a Poisson process: on average one brand-new (top-level) spam comment per day. Every spam post, comment or reply alike, itself attracts replies at an average rate of one per day. Over three days, how many spam posts (comments plus replies) can you expect in total?

The Riddler, FiveThirtyEight, April 10, 2020(original post)

Solution

This is a branching process in continuous time. Consider one post that has τ\tau days left in which to attract replies, and let f(τ)f(\tau) be the expected total number of posts in its whole reply tree, counting the post itself. The post spawns replies at rate 11; a reply born after uu days then has τ−u\tau - u days of its own, contributing f(τ−u)f(\tau - u). So f(τ)=1+∫0τf(τ−u) du=1+∫0τf(v) dv.f(\tau) = 1 + \int_0^{\tau} f(\tau - u)\,du = 1 + \int_0^{\tau} f(v)\,dv . Differentiating gives f′(τ)=f(τ)f'(\tau) = f(\tau) with f(0)=1f(0) = 1, so f(τ)=eτf(\tau) = e^{\tau}.

The top-level comments themselves arrive at rate 11 over the three days, and a top-level comment born at time ss has τ=3−s\tau = 3 - s days remaining, hence an expected tree of e3−se^{3-s} posts. Integrating over their arrival times, E[total]=∫03e3−s ds=∫03ev dv=e3−1≈19.09.\mathbb{E}[\text{total}] = \int_0^{3} e^{3-s}\,ds = \int_0^{3} e^{v}\,dv = e^{3} - 1 \approx \boxed{19.09}. (Equivalently, the expected count S(t)S(t) obeys dS/dt=SdS/dt = S once the column itself is treated as the seed post, giving S(3)=e3S(3) = e^3 and e3−1e^3 - 1 genuine spam posts.)

The computation

Encode the actual process: generate top-level arrivals as a rate-11 Poisson process on [0,3][0,3], let every post breed replies at rate 11 until day 33, and average the total count.

import random, math
rng = random.Random(0); T = 3.0; trials = 200_000; total = 0
for _ in range(trials):
    stack = []
    t = rng.expovariate(1.0)
    while t < T: stack.append(t); t += rng.expovariate(1.0)   # top-level arrivals
    n = 0
    while stack:
        born = stack.pop(); n += 1
        c = born + rng.expovariate(1.0)
        while c < T: stack.append(c); c += rng.expovariate(1.0)   # replies of this post
    total += n
print(total/trials, math.e**3 - 1)            # ~19.05, 19.086

The simulated mean (about 19.0519.05) matches e3−1≈19.09e^3 - 1 \approx 19.09, as boxed.

Report an error on this page

Reports are stored by Netlify. See the privacy note.