5 min read

Can you catch the cricket?

Table of Contents

Riddler Express

Help, there’s a cricket on my floor! I want to trap it with a cup so that I can safely move it outside. But every time I get close, it hops exactly 11 foot in a random direction.

I take note of its starting position and come closer. Boom β€” it hops in a random direction. I get close again. Boom β€” it takes another hop in a random direction, independent of the direction of the first hop.

What is the most probable distance between the cricket’s current position after two random jumps and its starting position? (Note: This puzzle is not asking for the expected distance, but rather the most probable distance. In other words, if you consider the probability distribution over all possible distances, where is the peak of this distribution?)

Solution

Let ΞΈΞΈ be the angle between the cricket’s jumps. Using the cosine law, we see that the distance from the center to the end point of the second hop is 2βˆ’2cos⁑θ\sqrt{2-2\cos\theta}. The least distance from the starting point is 00 and the maximum distance is 22. We can asssume that θ∼U[0,Ο€]ΞΈ \sim \mathcal{U}[0, Ο€].

For any real x∈[0,2]x ∈ [0, 2], we have the CDF of X=2βˆ’2cos⁑θX = \sqrt{2-2\cos\theta},

F(x)=P[X≀x]=P[2βˆ’2cos⁑θ≀x]=P[2βˆ’x22≀cos⁑θ]=P[arccos⁑(2βˆ’x22)β‰₯ΞΈ]=1Ο€arccos⁑(2βˆ’x22)\begin{aligned} F(x) &= \mathbb{P}[X \leq x] \\\\ &= \mathbb{P}[\sqrt{2-2 \cos \theta} \leq x] \\\\ &= \mathbb{P}[\frac{2 - x^2}{2}\leq \cos \theta ] \\\\ &= \mathbb{P}[\arccos \left(\frac{2 - x^2}{2} \right) \geq \theta ] \\\\ &= \frac{1}{\pi}\arccos \left(\frac{2 - x^2}{2}\right) \end{aligned}

Taking the derivative of the CDF, the PDF of XX is f(x)=2Ο€4βˆ’x2f(x) = \frac{2}{\pi\sqrt{4-x^2}} on [0,2][0, 2].

The PDF approaches infinity as x→2x \rightarrow 2, therefore the most probable distance is 2\textbf{2} feet.

Computational solution

From the histogram below, we see that the most probable distance is indeed 2\textbf{2} feet.

import numpy as np
from math import pi, sqrt, sin, cos
import matplotlib.pyplot as plt

def distances(num_samples = 1000000):
    def dist(row):
        return sqrt((cos(row[0])-cos(row[1]))**2 + (sin(row[0])-sin(row[1]))**2)
    angles = np.random.uniform(0, 2*pi, (num_samples,2))
    return np.apply_along_axis(dist, 1, angles)

def plot_dist_hist(distances):
    plt.hist(distances, bins='auto')
    plt.xlabel('Distance')
    plt.ylabel('Frequency')
    plt.title('Distance from the starting point')

plot_dist_hist(distances())

Riddler Classic

When you roll a pair of fair dice, the most likely outcome is 77 (which occurs 1/6 of the time) and the least likely outcomes are 22 and 1212 (which each occur 1/361/36 of the time).

Annoyed by the variance of these probabilities, I set out to create a pair of β€œuniform dice.” These dice still have sides that are uniquely numbered from 11 to 66, and they are identical to each other. However, they are weighted so that their sum is more uniformly distributed between 22 and 1212 than that of fair dice.

Unfortunately, it is impossible to create a pair of such dice so that the probabilities of all 1111 sums from 22 to 1212 are identical (i.e., they are all 1/111/11). But I bet we can get pretty close.

The variance of the 1111 probabilities is the average value of the squared difference between each probability and the average probability (which is, again, 1/111/11). One way to make my dice as uniform as possible is to minimize this variance.

So how should I make my dice as uniform as possible? In other words, which specific weighting of the dice minimizes the variance among the 1111 probabilities? That is, what should the probabilities be for rolling 1,2,3,4,51, 2, 3, 4, 5 or 66 with one of the dice?

Computational Solution

Let p1,p2,p3,p4,p5,p6p_1, p_2, p_3, p_4, p_5, p_6 be the probabilities for rolling 1,2,3,4,51, 2, 3, 4, 5 or 66 with one of the dice. We have βˆ‘i=16pi=1\sum_{i=1}^6 p_i= 1 and 0<pi<10 < p_i < 1 for i∈{1,…,6}i \in \{1, \dots,6\}. To calculate the variance among the 1111 probabilities, we first need to calculate P[sum=i]\mathbb{P}[sum = i] for i∈{2,…,12}i \in \{2, \dots,12\}. The probabilities are fairly straightforward to calculate e.g.

P[sum=2]=p12P[sum=3]=2p1p2P[sum=4]=p22+2p1p3P[sum=5]=2p1p4+2p2p3\begin{aligned} \mathbb{P}[sum=2] &= p_1^2 \\\\ \mathbb{P}[sum=3] &= 2p_1p_2 \\\\ \mathbb{P}[sum=4] &= p_2^2 + 2p_1p_3 \\\\ \mathbb{P}[sum=5] &= 2p_1p_4 + 2p_2p_3 \\\\ \end{aligned}

The variance is then given by

111βˆ‘i=212(P[sum=i]βˆ’111)2\frac{1}{11}\sum_{i=2}^{12}(\mathbb{P}[sum=i] - \frac{1}{11})^2

From the code below we see that the minimum value of the variance is 0.001217\textbf{0.001217} and the probabilities are p1=0.244p_1=\textbf{0.244}, p2=0.137p_2 = \textbf{0.137}, p3=0.118p_3 = \textbf{0.118}, p4=0.118p_4 = \textbf{0.118}, p5=0.137p_5 = \textbf{0.137} and p6=0.244p_6=\textbf{0.244}.

from scipy.optimize import minimize

def variance(probs):
    prob_sums={}
    for d1,d2 in [(i,j) for i in range(6) for j in range(6)]:
        prob_sums[d1+d2] = prob_sums.get(d1+d2, 0) + probs[d1]*probs[6+d2]
    return sum([(p - 1/11)**2 for p in prob_sums.values()])/11

minimize(variance, [0.5]*12, constraints=[{'type':'eq', 'fun':lambda probs:sum(probs[:6])-1}, 
                            {'type':'eq', 'fun':lambda probs:sum(probs[6:])-1}])

If we allow the two dice to have different weightings, we can do much better.From the code below we see that the minimum value of the variance is 0.000258\textbf{0.000258} and the probabilities are p1=0.5p_1=\textbf{0.5}, p2=0p_2 = \textbf{0}, p3=0p_3 = \textbf{0}, p4=0p_4 = \textbf{0}, p5=0p_5 = \textbf{0} and p6=0.5p_6=\textbf{0.5} for the first die and p1=0.125p_1=\textbf{0.125}, p2=0.186p_2 = \textbf{0.186}, p3=0.189p_3 = \textbf{0.189}, p4=0.189p_4 = \textbf{0.189}, p5=0.186p_5 = \textbf{0.186} and p6=0.125p_6=\textbf{0.125} for the second.

minimize(variance, [0.5]*12, bounds=[(0,1)]*12, 
                            constraints=[{'type':'eq', 'fun':lambda probs:sum(probs[:6])-1}, 
                            {'type':'eq', 'fun':lambda probs:sum(probs[6:])-1},
                            {'type':'eq', 'fun':lambda probs:probs[0]-0.5}])