Jane Street Puzzle: Beside the Point

Presenting my solution to the Beside the Point puzzle

Posted by Krystian Wojcicki on Monday, December 2, 2024 Tags: Tutorial   11 minute read

Introduction

In Jane Street’s latest puzzle, Beside the Point, we’re given the following prompt

Two random points, one red and one blue, are chosen uniformly and independently from the interior of a square. To ten decimal places, what is the probability that there exists a point on the side of the square closest to the blue point that is equidistant to both the blue point and the red point?

As well as a visual depiction

Solution

point on the side of the square closest to the blue point that is equidistant to both the blue point and the red point

Without loss of generality let’s assume the blue point is within the triangle defined by \((0,0), (0.5,0.5) \textrm{ and } (1,0)\). To find an equidistant point we can envision a circle with a centroid at \((a, 0)\) (i.e. on the x-axis) and the red and blue points lying on the circle’s border.

If we are given two points we can determine \(a\) via the following equation:

\[\begin{aligned} P_{blue} = P_b &= (x_1, y_1) \\ P_{red} = P_r &= (x_2, y_2) \\ \textrm{Circle Centroid} &= (a, 0) \textrm{ s.t. } 0 \leq a \leq 1 \\ (x_1 - a)^2 + (y_1 - 0)^2 &= r^2 \\ (x_2 - a)^2 + (y_2 - 0)^2 &= r^2 \\ \end{aligned}\] \[\begin{aligned} (x_1 - a)^2 + (y_1 - 0)^2 &= (x_2 - a)^2 + (y_2 - 0)^2 \\ (x_1 - a)^2 + y_1^2 &= (x_2 - a)^2 + y_2^2 \\ (x_1 - a)^2 - (x_2 - a)^2 &= y_2^2 - y_1^2 \\ x_1^2 - 2x_1a - a^2 - x_2^2 + 2x_2a + a^2 &= y_2^2 - y_1^2 \\ x_1^2 - x_2^2 - 2x_1a + 2x_2a &= y_2^2 - y_1^2 \\ -2x_1a + 2x_2a &= y_2^2 - y_1^2 - x_1^2 + x_2^2 \\ 2a(x_2 - x_1) &= y_2^2 - y_1^2 - x_1^2 + x_2^2 \\ a &= \frac{(y_2^2 - y_1^2 - x_1^2 + x_2^2)}{2(x_2 - x_1)} \\ \end{aligned}\]

Which gives us the equation for the circle, with \((a,0)\) as it’s centroid and the blue/red point lying on the border, as

\[(x - a)^2 + y^2 = (a - x_1)^2 + (0-y)^2\]

We can represent the area for which \(a\) is defined (when give the blue point) as the area of the following circles:

\[x ^ 2 + y^2 = x_1^2 + y^2 \\ x^2 + y^2 -2x = x_1^2 +y_1^2 - 2x_1\]

Visualization of the solution

The above clip visually shows how the two circles defined above encompass the entire valid area for the red point. You can play with the demo yourself here.

The intersection of these two circles needs to be removed (formulas taken from here)

\[r_1 = \sqrt{(x_1^2 + y_1^2)} \\ r_2 = \sqrt{((x_1-1)^2 + y_1^2)} \\ c_{bd} = 2 * \arccos{\frac{r_2^2 + 1 - r_1^2}{2r_2}} \\ c_{ad} = 2 * \arccos{\frac{r_1^2 + 1 - r_2^2}{2r_0}} \\ \textrm{intersection area} = \frac{1}{2}r_2^2(c_{bd} - \sin(c_{bd})) + \frac{1}{2}r_1^2(c_{ad} - \sin(c_{ad}))\]

Therefore given a blue point the probability that there exists a point on the side of the square that is equidistant to both the blue point and the red point is:

\[P = \textrm{Area of the circle defined by a = 0} + \textrm{Area of the circle defined by a = 1} - \textrm{intersection area} \\ = \frac{pi * r_1^2}{4} + \frac{pi * r_2^2}{4} - \textrm{intersection area}\]

To find the general probability (i.e. given any blue point) we can do a double integration

\[8 * \int_0^{0.5}{\int_0^{x} \frac{\pi r_1^2}{4} + \frac{\pi r_2^2}{4} - \textrm{intersection area } dy dx}\]

Which we can use scipy to integrate:

from scipy import integrate
import numpy as np

f_r1 = lambda x,y: np.sqrt(x * x + y * y)
f_r2 = lambda x,y: np.sqrt((x-1.0) * (x-1.0) + y * y)
f_cbd = lambda r0, r1: 2 * np.arccos( (r1 * r1 + 1 - r0 * r0) / (2 * r1 ))
f_cad = lambda r0, r1: 2 * np.arccos( (r0 * r0 + 1 - r1 * r1) / (2 * r0 ))

f_intersection = lambda r0, r1, cbd, cad: (1/2) * cbd * r1 * r1 - 1/2 * r1 * r1 * np.sin(cbd) \
+ (1/2) * cad * r0 * r0 - (1/2) * r0 * r0 * np.sin(cad)

f_area = lambda y,x: (np.pi * f_r1(x,y) * f_r1(x,y) / 4.0) + \
(np.pi * f_r2(x,y) * f_r2(x,y) / 4.0) - \
f_intersection(
    f_r1(x,y),
    f_r2(x,y),
    f_cbd(f_r1(x,y), f_r2(x,y)),
    f_cad(f_r1(x,y), f_r2(x,y))
)

res = integrate.dblquad(f_area, 0, 0.5, 0, lambda x: x)
print(res[0] * 8, res[1])
# 0.49140757883830793 2.485643838466147e-15

Providing a final answer of 0.4914075788

Brute force

We can double check this by performing trillions of trial runs:

  • Generate a random point within the triangle defined as \(ABC\)
  • Generate a random independent point in the unit square
  • Calculate \(a\) as shown above
  • If \(a\) is between 0 and 1 (inclusive on both ends) increment the success counter
  • Increment the trial counter
  • Print (success / trial)
public static void bruteMiniForce() {
	int counter = 0;
	BigDecimal trials = BigDecimal.ZERO;
	BigDecimal success = BigDecimal.ZERO;
	double x1 = 0, y1 = 0, x2 = 0, y2 = 0;
	double r1 = 0, r2 = 0;
	Random r = new Random();

	while(true) {

		r1 = r.nextDouble();
		r2 = r.nextDouble();
		x2 = r.nextDouble();
		y2 = r.nextDouble();

		if(r1 == 0 || r2 == 0 || x2 == 0 || y2 == 0) continue;

		// https://stackoverflow.com/questions/19654251/random-point-inside-triangle-inside-java
		// x = (1 - Math.sqrt(r1)) * 0 + (Math.sqrt(r1) * (1 - r2)) * 0.5 + (Math.sqrt(r1) * r2) * 1;
		x1 = (Math.sqrt(r1) * (1 - r2)) * 0.5 + (Math.sqrt(r1) * r2) * 1;
		// y = (1 - Math.sqrt(r1)) * 0 + (Math.sqrt(r1) * (1 - r2)) * 0.5 + (Math.sqrt(r1) * r2) * 0;
		y1 = (Math.sqrt(r1) * (1 - r2)) * 0.5;

		double centroid = (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1) / (2  * (x2 - x1));

		if(centroid >= 0 && centroid <= 1) success = success.add(BigDecimal.ONE);

		trials = trials.add(BigDecimal.ONE);
		counter++;

		if(counter == 1_000_000_000) {
			counter = 0;
			System.out.println(trials + " " + (success.divide(trials, MathContext.DECIMAL64).doubleValue()));
		}
	}
}

Which after 195_000_000_000 trials provides a probability of 0.4914080657435897. Only differing from the correct answer at the 6th decimal digit.