My friend Eliška got a cake from Merci chocolate bars and Ferrero Rocher, attached to a base from polystyrene. It was really finely done, with satisfactory geometric regularity.

That got us thinking: how does one even estimate, which base size to buy, not knowing how many Merci pieces fit around its circumference.

The first step is to measure a width of Merci piece, $m$, which is fixed (at least until the next shrinkflation). Based on my measurements in Linz, Austria on 23 March 2025, $m=1.9$ cm.

m = 1.9  # merci width

Next, we tile a circle of radius $r$ with $k$ Merci pieces -- both $r$ and $k$ are unknown. We want to keep the tiling of the circumference as perfect as possible, i.e., minimize the remaining gap $\epsilon\in[0,m)$ where the bar cannot fit anymore as small as possible.

Models

Circular model

The first model simplifies Merci to an arc of the length $m$ on the circle of the sought radius $r$.

This implies $k$ Mercis reach the length of $k m$ and the total length is $2\pi r$. The full model along with the tiling gap is

$$ 2\pi r=k\cdot m+\epsilon. $$

We can actually directly estimate $k$ as $k=\lfloor\frac{2\pi r}{m}\rfloor$. For the $k$ estimate, we then calculate the gap $\epsilon$.

Polygon model

Our second attempt is a polygon model with the circular base inscribed inside.

This way, we express the relationship of $m$ and $k$ as

$$ \tan\left(\frac{\pi}{k}\right)=\frac{m}{2r}. $$

We convert this to arc lengths, to allow for the tiling gap $\epsilon$ as before.

$$ 2\pi r = 2kr\arctan\left(\frac{m}{2r}\right)+\epsilon. $$

Results

We assess the quantization error over different choices of $r$ and $k$.

import numpy as np
import pandas as pd

df = []
for r in np.arange(4.5,6.5,.1):
    k1 = int(np.floor(2*np.pi*r / m))
    k2 = int(np.floor(np.pi / np.atan(m/2/r)))
    df.append({
        'r': r,
        'circ0': 2*np.pi*r,
        'm': m,
        # circle model

        'k1': k1,
        'eps1': 2*np.pi*r - k1*m,
        'circ1': k1*m,
        # polygon model

        'k2': k2,
        'eps2': 2*np.pi*r - 2*k2*r * np.atan(m/2/r),
        'circ2': 2*k2*r * np.atan(m/2/r),
    })
df = pd.DataFrame(df)

The results for both models are presented in the table below.

$r$ $2\pi r$ $k_\circ$ $k_\circ m$ $\epsilon_\circ$ $k_{\text{⬡}}$ $2k_{\text{⬡}}r\arctan(\frac{m}{2r})$ $\epsilon_{\text{⬡}}$
4.528.2741426.61.6741528.0880.187
4.628.9031528.50.4031528.1050.798
4.729.5311528.51.0311528.1211.410
4.830.1591528.51.6591630.0120.147
4.930.7881630.40.3881630.0270.760
5.031.4161630.41.0161630.0421.374
5.132.0441630.41.6441731.9340.110
5.232.6731732.30.3731731.9480.725
5.333.3011732.31.0011731.9611.340
5.433.9291732.31.6291833.8540.076
5.534.5581834.20.3581833.8660.692
5.635.1861834.20.9861833.8771.308
5.735.8141834.21.6141935.7710.043
5.836.4421936.10.3421935.7820.660
5.937.0711936.10.9711935.7931.278
6.037.6991936.11.5992037.6870.012
6.138.3272038.00.3272037.6970.630
6.238.9562038.00.9562037.7071.249
6.339.5842038.01.5842037.7161.868
6.440.2122139.90.3122139.6110.602

Practical assessment

TBD