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...
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.

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 converges uniformly on .
Proof. Since for all , each term satisfies . The series converges, so by the Weierstrass -test, converges uniformly.
Theorem 2 (Continuity and Non-Differentiability). is continuous everywhere and differentiable nowhere on .
Proof. Continuity follows from the uniform limit of continuous functions . Nowhere-differentiability is the classical Takagi theorem (1903).
Lemma 1 (Truncation Error). Truncating the series at terms gives error bounded by :
Proof. Direct from and geometric series summation.
Theorem 3 (Symmetry). for all .
Proof. for all (distance to nearest integer is symmetric about modulo 1). Hence for all (since and is periodic with period 1).
Lemma 2 (Circle Arcs). The circle has lower and upper arcs on :
Proof. Solve for .
Theorem 4 (Intersection and Area). The Blancmange curve intersects the circle at (where ) and at some . Between and , the curve lies above the lower arc and inside . The enclosed area is
Proof. At : and , confirming the point lies on . The left intersection is the unique root of on (verified numerically). Between and , the Blancmange curve lies above and below , so the area between the curve and the lower arc gives the enclosed region.
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: where (series terms) and (quadrature points). Total: floating-point operations.
- Space: (each quadrature point is computed on the fly).
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#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;
}
"""
Problem 226: A Scoop of Blancmange
Find the area under the Blancmange curve enclosed by the circle
(x - 1/4)^2 + (y - 1/2)^2 = 1/16, to 8 decimal places.
"""
import math
def s(x):
"""Triangle wave: distance to nearest integer."""
return abs(x - round(x))
def blanc(x, terms=60):
"""Blancmange (Takagi) curve value at x."""
result = 0.0
pow2 = 1.0
for _ in range(terms):
result += s(pow2 * x) / pow2
pow2 *= 2.0
return result
def on_circle(x):
"""Returns (x-1/4)^2 + (blanc(x)-1/2)^2 - 1/16. Zero on circle."""
b = blanc(x)
return (x - 0.25)**2 + (b - 0.5)**2 - 1.0/16
def circle_lower(x):
"""Lower arc of circle: y = 1/2 - sqrt(1/16 - (x-1/4)^2)."""
val = 1.0/16 - (x - 0.25)**2
if val < 0:
return 0.5
return 0.5 - math.sqrt(val)
def bisect_root(f, a, b, tol=1e-14):
"""Find root of f in [a, b] using bisection."""
fa, fb = f(a), f(b)
if fa * fb > 0:
return a
for _ in range(100):
mid = (a + b) / 2
fm = f(mid)
if abs(b - a) < tol:
return mid
if fa * fm <= 0:
b, fb = mid, fm
else:
a, fa = mid, fm
return (a + b) / 2
def integrand(x):
"""blanc(x) - circle_lower(x)"""
return blanc(x) - circle_lower(x)
def simpsons(f, a, b, n):
"""Simpson's rule with n subdivisions (n must be even)."""
h = (b - a) / n
result = f(a) + f(b)
for i in range(1, n):
x = a + i * h
result += (2 if i % 2 == 0 else 4) * f(x)
return result * h / 3
# Find intersection point
x1 = bisect_root(on_circle, 0.05, 0.1)
x2 = 0.5
# Compute area using Simpson's rule with fine grid
N = 100000 # 100K subdivisions for reasonable Python speed
area = simpsons(integrand, x1, x2, N)
print(f"{area:.8f}")
# Optional visualization