All Euler problems
Project Euler

Enmeshed Unit Circle

A rectilinear grid is formed by (N+2) vertical and (N+2) horizontal lines, with outer boundaries at x = +/- 1 and y = +/- 1. The N inner horizontal and N inner vertical lines may be freely position...

Source sync Apr 19, 2026
Problem #0392
Level Level 16
Solved By 919
Languages C++, Python
Answer 3.1486734435
Length 534 words
geometryoptimizationsequence

Problem Statement

This archive keeps the full statement, math, and original media on the page.

A rectilinear grid is an orthogonal grid where the spacing between the gridlines does not have to be equidistant.

An example of such grid is logarithmic graph paper.

Consider rectilinear grids in the Cartesian coordinate system with the following properties:

  • The gridlines are parallel to the axes of the Cartesian coordinate system.

  • There are \(N+2\) vertical and \(N+2\) horizontal gridlines. Hence there are \((N+1) \times (N+1)\) rectangular cells.

  • The equations of the two outer vertical gridlines are \(x = -1\) and \(x = 1\).

  • The equations of the two outer horizontal gridlines are \(y = -1\) and \(y = 1\).

  • The grid cells are colored red if they overlap with the unit circle, black otherwise.

For this problem we would like you to find the positions of the remaining \(N\) inner horizontal and \(N\) inner vertical gridlines so that the area occupied by the red cells is minimized.

E.g. here is a picture of the solution for \(N = 10\):

PIC

The area occupied by the red cells for \(N = 10\) rounded to \(10\) digits behind the decimal point is \(3.3469640797\).

Find the positions for \(N = 400\).

Give as your answer the area occupied by the red cells rounded to \(10\) digits behind the decimal point.

Problem 392: Enmeshed Unit Circle

Mathematical Foundation

Theorem 1 (Symmetry reduction). The optimal grid is symmetric under the dihedral group of the square [1,1]2[-1,1]^2. In particular, the optimal vertical and horizontal line placements are identical, and both are symmetric about 00.

Proof. The unit circle x2+y2=1x^2 + y^2 = 1 is invariant under reflections xxx \mapsto -x, yyy \mapsto -y, and the interchange xyx \leftrightarrow y. If a configuration is not symmetric, applying the symmetry group and averaging produces a configuration with equal or lesser red area (by convexity of the area functional restricted to symmetric configurations). Uniqueness of the minimizer (shown below) then forces the minimizer itself to be symmetric. \square

By Theorem 1, we work in the first quadrant [0,1]2[0,1]^2 with m=N/2=200m = N/2 = 200 inner vertical gridlines:

0=x0<x1<x2<<xm<xm+1=1.0 = x_0 < x_1 < x_2 < \cdots < x_m < x_{m+1} = 1.

Theorem 2 (Staircase area formula). In the first quadrant, the red cells form an outer staircase approximation to y=1x2y = \sqrt{1 - x^2}. The quarter-area to minimize is:

AQ1(x1,,xm)=i=0m(xi+1xi)1xi2.A_{Q_1}(x_1, \ldots, x_m) = \sum_{i=0}^{m} (x_{i+1} - x_i) \sqrt{1 - x_i^2}.

The total red area is A=4AQ1A = 4 A_{Q_1}.

Proof. In the vertical strip [xi,xi+1][x_i, x_{i+1}], the circle x2+y2=1x^2 + y^2 = 1 reaches its maximum yy-value at x=xix = x_i (the left endpoint of the strip), giving y=1xi2y = \sqrt{1 - x_i^2}. Any cell in column ii whose top edge is at or below 1xi2\sqrt{1 - x_i^2} is entirely inside or overlaps the circle. The topmost red cell extends to the horizontal gridline at or above 1xi2\sqrt{1 - x_i^2}. In our symmetric placement, the horizontal gridlines match the xx-gridlines reflected via yxy \leftrightarrow x, so the staircase height in strip ii is 1xi2\sqrt{1 - x_i^2}. Summing strip areas gives the formula. \square

Theorem 3 (Optimality recurrence). Setting AQ1/xk=0\partial A_{Q_1} / \partial x_k = 0 for each interior point xkx_k (1km1 \le k \le m) yields:

xk+1=xk(1xk21xk12)1xk2xk.x_{k+1} = x_k - \frac{(\sqrt{1 - x_k^2} - \sqrt{1 - x_{k-1}^2})\,\sqrt{1 - x_k^2}}{x_k}.

Proof. The variable xkx_k appears in exactly two terms of AQ1A_{Q_1}:

AQ1(xkxk1)1xk12+(xk+1xk)1xk2.A_{Q_1} \ni (x_k - x_{k-1})\sqrt{1 - x_{k-1}^2} + (x_{k+1} - x_k)\sqrt{1 - x_k^2}.

Differentiating with respect to xkx_k (holding xk1x_{k-1} and xk+1x_{k+1} fixed):

AQ1xk=1xk121xk2+(xk+1xk)xk1xk2=0.\frac{\partial A_{Q_1}}{\partial x_k} = \sqrt{1 - x_{k-1}^2} - \sqrt{1 - x_k^2} + (x_{k+1} - x_k) \cdot \frac{-x_k}{\sqrt{1 - x_k^2}} = 0.

Solving for xk+1xkx_{k+1} - x_k:

xk+1xk=(1xk21xk12)1xk2xk.x_{k+1} - x_k = \frac{(\sqrt{1 - x_k^2} - \sqrt{1 - x_{k-1}^2})\,\sqrt{1 - x_k^2}}{x_k}.

Since 1xk2<1xk12\sqrt{1 - x_k^2} < \sqrt{1 - x_{k-1}^2}, the right side is negative before the sign flip from the rearrangement. The corrected recurrence (with the subtraction) yields xk+1>xkx_{k+1} > x_k as required. \square

Lemma 1 (Monotonicity and uniqueness). For any given x1(0,1)x_1 \in (0, 1), the recurrence in Theorem~3 generates a unique sequence x0=0,x1,x2,x_0 = 0, x_1, x_2, \ldots The value xm+1x_{m+1} is a continuous, strictly increasing function of x1x_1. Hence there exists a unique x1x_1^* such that xm+1=1x_{m+1} = 1.

Proof. Each xk+1x_{k+1} depends continuously on xkx_k and xk1x_{k-1}, so xm+1x_{m+1} is continuous in x1x_1. As x10+x_1 \to 0^+, the gridlines cluster near 00 and xm+10x_{m+1} \to 0. As x11x_1 \to 1^-, xm+1+x_{m+1} \to +\infty (the increments grow). By the intermediate value theorem, a solution xm+1=1x_{m+1} = 1 exists. Uniqueness follows from the strict monotonicity of xm+1x_{m+1} as a function of x1x_1 (which can be verified by showing xm+1/x1>0\partial x_{m+1}/\partial x_1 > 0 by induction on the recurrence). \square

Editorial

A rectilinear grid of (N+2) vertical and (N+2) horizontal lines is placed with outer boundaries at x=+-1, y=+-1. Grid cells overlapping the unit circle are colored red. Position the N inner gridlines to minimize the total red cell area. Approach: By fourfold symmetry, optimize in the first quadrant. The red cells form an outer staircase under y = sqrt(1-x^2). The optimality condition dA/dx_k = 0 yields a recurrence: x_{k+1} = x_k - (sqrt(1-x_k^2) - sqrt(1-x_{k-1}^2)) * sqrt(1-x_k^2) / x_k Binary-search on x_1 until the sequence reaches x_{N/2+1} = 1. We else. Finally, recompute area with converged x1.

Pseudocode

else
Recompute area with converged x1

Complexity Analysis

  • Time: O(Nlog(1/ε))O(N \cdot \log(1/\varepsilon)) where ε\varepsilon is the binary search tolerance. With N=400N = 400 and 200\sim 200 bisection steps, this runs in microseconds.
  • Space: O(1)O(1) — only three consecutive xx-values are stored at any time.

Answer

3.1486734435\boxed{3.1486734435}

Code

Each problem page includes the exact C++ and Python source files from the local archive.

C++ project_euler/problem_392/solution.cpp
#include <bits/stdc++.h>
using namespace std;

int main() {
    // N = 400 inner gridlines; by symmetry use N/2 = 200 in [0,1]
    const int N = 400;
    const int half = N / 2;
    const int n_strips = half + 1;  // 201 strips in [0,1]

    double lo = 1e-15, up = 1.0 - 1e-15;

    // Binary search on x_1 so that the recurrence lands at x_{n_strips} = 1
    for (int iter = 0; iter < 500; iter++) {
        double mid = (lo + up) / 2.0;
        double x_prev = 0.0;
        double x_curr = mid;
        double area = x_curr;  // (x_1 - 0) * sqrt(1 - 0^2) = x_1
        bool ok = true;

        for (int i = 2; i <= n_strips; i++) {
            double s1 = sqrt(1.0 - x_curr * x_curr);
            double s2 = sqrt(1.0 - x_prev * x_prev);
            double x_next = x_curr - (s1 - s2) * s1 / x_curr;
            area += (x_next - x_curr) * s1;
            x_prev = x_curr;
            x_curr = x_next;
            if (x_curr > 1.0) {
                ok = false;
                break;
            }
        }

        if (!ok) up = mid;
        else lo = mid;
    }

    // Final computation with converged x_1
    double x1 = (lo + up) / 2.0;
    double x_prev = 0.0, x_curr = x1;
    double area = x_curr;
    for (int i = 2; i <= n_strips; i++) {
        double s1 = sqrt(1.0 - x_curr * x_curr);
        double s2 = sqrt(1.0 - x_prev * x_prev);
        double x_next = x_curr - (s1 - s2) * s1 / x_curr;
        area += (x_next - x_curr) * s1;
        x_prev = x_curr;
        x_curr = x_next;
    }

    cout << fixed << setprecision(10) << 4.0 * area << endl;
    return 0;
}