Presented by Timandra Harkness and Matt Parker in Can you solve The Frog Problem?
Imagine some number of lilypads spanning a river in a line, and a frog at one bank. The frog wants to cross the river. To move forward, it selects one of the lilypads with uniform probability (or the far bank, which we include as an option), hops there, selects a new position closer to its destination, and repeats this process until it eventually reaches the far side.
For a given number of lilypads $p$, what is the expected number of jumps for the frog to make it across the river?
Let
Multiplying by
Expanding and simplifying the equation:
This telescopes directly to the
For a river with
For large values of
where
Let
Because a jump from distance
Subtracting the relation for
Applying this inductively over the total distance
The probability of taking exactly
We obtain these coefficients computationally by convolving the linear term coefficient vectors
The code in this notebook uses functions from the numpy and matplotlib modules.
import numpy as np # vectorized math operations
from matplotlib import pyplot as pl # plots pointsTo compute the probability of taking exactly
def lengthProbDistribution(p):
"""
Computes the probability of taking k steps for all k in [1, p+1].
Returns a numpy array of probabilities where index i corresponds to k = i + 1.
"""
poly = np.array([1.0])
for i in range(1, p + 2):
poly = np.convolve(poly, [1.0 / i, (i - 1.0) / i])
# The poly array contains coefficients in descending order of powers: [x^(p+1), ..., x^1, x^0]
# We reverse it to ascending order, and drop the constant x^0 term (which is always 0.0)
return poly[::-1][1:]
def lengthProb(p, k):
"""
Returns the probability of taking exactly k steps with p lilypads.
"""
if k < 1 or k > p + 1:
return 0.0
dist = lengthProbDistribution(p)
return dist[k - 1]The expectation is calculated directly in
def expectedSteps(p):
"""
Returns the expected number of steps for p lilypads.
"""
return np.sum(1.0 / np.arange(1, p + 2))lengthProb(4, 1)0.2
p = 5
dist = lengthProbDistribution(p)
print(np.sum(dist))1.0
expectedSteps(1)1.5
Because the calculations are mathematically optimized, we can plot the expected values across a larger range of
# Values of p to check
lowP = 0
highP = 500
# Plot points
x = range(lowP, highP + 1)
y = [expectedSteps(p) for p in x]
pl.figure(figsize=(10, 6))
pl.plot(x, y, 'ko', markersize=4)
pl.xlabel('Number of lilypads')
pl.ylabel('Expected number of jumps')
pl.title('Expected Jumps vs. Number of Lilypads')
pl.grid(True, linestyle='--', alpha=0.5)
pl.show()© Copyright 2026 Blake Rayvid. All rights reserved.
