All Euler problems
Project Euler

A Scoop of Blancmange

The Blancmange curve (Takagi curve) is defined by blanc(x) = sum_(n=0)^infinity (s(2^n x))/(2^n) where s(x) = min_(k in Z) |x - k| is the distance from x to the nearest integer. Consider the circle...

Source sync Apr 19, 2026
Problem #0226
Level Level 10
Solved By 2,047
Languages C++, Python
Answer 0.11316017
Length 290 words
geometrymodular_arithmeticalgebra

Problem Statement

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

The blancmange curve is the set of points $(x, y)$ such that $0 \le x \le 1$ and $\displaystyle y = \sum \limits_{n = 0}^{\infty} {\dfrac{s(2^n x)}{2^n}}$, where $s(x)$ is the distance from $x$ to the nearest integer.

The area under the blancmange curve is equal to ½, shown in pink in the diagram below.

Problem illustration

Let $C$ be the circle with centre $\left ( \frac{1}{4}, \frac{1}{2} \right )$ and radius $\frac{1}{4}$, shown in black in the diagram.

What area under the blancmange curve is enclosed by $C$?

Give your answer rounded to eight decimal places in the form $0.abcdefgh$.

Problem 226: A Scoop of Blancmange

Mathematical Foundation

Theorem 1 (Convergence of the Blancmange Series). The series blanc(x)=n=0s(2nx)2n\operatorname{blanc}(x) = \sum_{n=0}^{\infty} \frac{s(2^n x)}{2^n} converges uniformly on R\mathbb{R}.

Proof. Since 0s(t)1/20 \leq s(t) \leq 1/2 for all tt, each term satisfies 0s(2nx)2n12n+10 \leq \frac{s(2^n x)}{2^n} \leq \frac{1}{2^{n+1}}. The series n=012n+1=1\sum_{n=0}^{\infty} \frac{1}{2^{n+1}} = 1 converges, so by the Weierstrass MM-test, blanc(x)\operatorname{blanc}(x) converges uniformly. \square

Theorem 2 (Continuity and Non-Differentiability). blanc(x)\operatorname{blanc}(x) is continuous everywhere and differentiable nowhere on [0,1][0,1].

Proof. Continuity follows from the uniform limit of continuous functions s(2nx)/2ns(2^n x)/2^n. Nowhere-differentiability is the classical Takagi theorem (1903). \square

Lemma 1 (Truncation Error). Truncating the series at NN terms gives error bounded by 2N2^{-N}:

blanc(x)n=0N1s(2nx)2nn=N12n+1=12N.\left|\operatorname{blanc}(x) - \sum_{n=0}^{N-1} \frac{s(2^n x)}{2^n}\right| \leq \sum_{n=N}^{\infty} \frac{1}{2^{n+1}} = \frac{1}{2^N}.

Proof. Direct from s(t)1/2|s(t)| \leq 1/2 and geometric series summation. \square

Theorem 3 (Symmetry). blanc(x)=blanc(1x)\operatorname{blanc}(x) = \operatorname{blanc}(1 - x) for all xx.

Proof. s(t)=s(1t)s(t) = s(1 - t) for all tt (distance to nearest integer is symmetric about 1/21/2 modulo 1). Hence s(2nx)=s(2n(1x))s(2^n x) = s(2^n(1-x)) for all nn (since 2n(1x)=2n2nx2^n(1-x) = 2^n - 2^n x and ss is periodic with period 1). \square

Lemma 2 (Circle Arcs). The circle CC has lower and upper arcs on [0,1/2][0, 1/2]:

ylow(x)=12116(x14)2,yup(x)=12+116(x14)2.y_{\text{low}}(x) = \frac{1}{2} - \sqrt{\frac{1}{16} - \left(x - \frac{1}{4}\right)^2}, \quad y_{\text{up}}(x) = \frac{1}{2} + \sqrt{\frac{1}{16} - \left(x - \frac{1}{4}\right)^2}.

Proof. Solve (x1/4)2+(y1/2)2=1/16(x - 1/4)^2 + (y - 1/2)^2 = 1/16 for yy. \square

Theorem 4 (Intersection and Area). The Blancmange curve intersects the circle at x2=1/2x_2 = 1/2 (where blanc(1/2)=1/2\operatorname{blanc}(1/2) = 1/2) and at some x10.0789x_1 \approx 0.0789. Between x1x_1 and x2x_2, the curve lies above the lower arc and inside CC. The enclosed area is

A=x1x2[blanc(x)ylow(x)]dx.A = \int_{x_1}^{x_2}\bigl[\operatorname{blanc}(x) - y_{\text{low}}(x)\bigr]\,dx.

Proof. At x=1/2x = 1/2: blanc(1/2)=1/2\operatorname{blanc}(1/2) = 1/2 and (1/21/4)2+(1/21/2)2=1/16(1/2 - 1/4)^2 + (1/2 - 1/2)^2 = 1/16, confirming the point lies on CC. The left intersection x1x_1 is the unique root of (x1/4)2+(blanc(x)1/2)2=1/16(x - 1/4)^2 + (\operatorname{blanc}(x) - 1/2)^2 = 1/16 on (0,1/2)(0, 1/2) (verified numerically). Between x1x_1 and x2x_2, the Blancmange curve lies above ylow(x)y_{\text{low}}(x) and below yup(x)y_{\text{up}}(x), so the area between the curve and the lower arc gives the enclosed region. \square

Editorial

We find x1 by Brent’s method on f(x) = (x-1/4)^2 + (blanc(x)-1/2)^2 - 1/16. Finally, simpson’s rule with M subdivisions.

Pseudocode

Find x1 by Brent's method on f(x) = (x-1/4)^2 + (blanc(x)-1/2)^2 - 1/16
Simpson's rule with M subdivisions

Complexity Analysis

  • Time: O(NM)O(N \cdot M) where N=60N = 60 (series terms) and M=2×106M = 2 \times 10^6 (quadrature points). Total: 1.2×108\approx 1.2 \times 10^8 floating-point operations.
  • Space: O(1)O(1) (each quadrature point is computed on the fly).

Answer

0.11316017\boxed{0.11316017}

Code

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

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

// Triangle wave: distance to nearest integer
double s(double x) {
    return abs(x - round(x));
}

// Blancmange curve value at x (60 terms suffice for ~18 digit precision)
double blanc(double x) {
    double result = 0.0;
    double pow2 = 1.0;
    for (int n = 0; n < 60; n++) {
        result += s(pow2 * x) / pow2;
        pow2 *= 2.0;
    }
    return result;
}

// Circle: (x - 1/4)^2 + (y - 1/2)^2 = 1/16
// Lower arc: y = 1/2 - sqrt(1/16 - (x - 1/4)^2)
double circle_lower(double x) {
    double val = 1.0 / 16.0 - (x - 0.25) * (x - 0.25);
    if (val < 0) return 0.5;
    return 0.5 - sqrt(val);
}

// Function whose root gives the intersection point
double on_circle(double x) {
    double b = blanc(x);
    return (x - 0.25) * (x - 0.25) + (b - 0.5) * (b - 0.5) - 1.0 / 16.0;
}

// Brent's method to find root in [a, b]
double brent(double a, double b, double tol = 1e-15) {
    double fa = on_circle(a), fb = on_circle(b);
    if (fa * fb > 0) return a;
    double c = a, fc = fa, d = b - a, e = d;
    for (int i = 0; i < 200; i++) {
        if (fb * fc > 0) { c = a; fc = fa; d = e = b - a; }
        if (fabs(fc) < fabs(fb)) { a = b; b = c; c = a; fa = fb; fb = fc; fc = fa; }
        double tol1 = 2e-16 * fabs(b) + 0.5 * tol;
        double m = 0.5 * (c - b);
        if (fabs(m) <= tol1 || fb == 0) return b;
        if (fabs(e) >= tol1 && fabs(fa) > fabs(fb)) {
            double s_val;
            if (a == c) {
                s_val = fb / fa; double p = 2 * m * s_val; double q = 1 - s_val;
                if (p > 0) q = -q; else p = -p;
                if (2*p < 3*m*q - fabs(tol1*q) && 2*p < fabs(e*q)) { e = d; d = p/q; }
                else { d = m; e = m; }
            } else { d = m; e = m; }
        } else { d = m; e = m; }
        a = b; fa = fb;
        if (fabs(d) > tol1) b += d;
        else b += (m > 0 ? tol1 : -tol1);
        fb = on_circle(b);
    }
    return b;
}

int main() {
    // Find intersection point x1
    double x1 = brent(0.05, 0.1);
    double x2 = 0.5;

    // Integrand: blanc(x) - circle_lower(x)
    auto integrand = [](double x) -> double {
        return blanc(x) - (0.5 - sqrt(max(0.0, 1.0 / 16.0 - (x - 0.25) * (x - 0.25))));
    };

    // Simpson's rule with 2M subdivisions
    int N = 2000000;
    double h = (x2 - x1) / N;
    double sum = integrand(x1) + integrand(x2);

    for (int i = 1; i < N; i++) {
        double x = x1 + i * h;
        sum += (i % 2 == 0 ? 2.0 : 4.0) * integrand(x);
    }

    double area = sum * h / 3.0;
    printf("%.8f\n", area);
    return 0;
}