The pizza theorem

Does a pizza have to be cut through its center to be shared fairly? The pizza theorem says that it does not. Four straight cuts through any point of a round pizza, at 45° to each other, make eight slices of different sizes, yet two people who take every other slice get the same amount of pizza and the same amount of crust. L. J. Upton posed this as a problem, and Michael Goldberg’s solution showed that it holds for every even number of cuts from four on, which makes 8, 12, 16 or more slices.

With other numbers of cuts, the two shares differ unless a cut passes through the center. Rick Mabry and Paul Deiermann proved which share gets more and how the crust is shared:

  • With 1, 2, 3, 7, 11, 15, … cuts, the share that holds the center gets more pizza.

  • With 5, 9, 13, … cuts, the other share gets more.

  • With an even number of cuts, both shares get the same crust. With an odd number from three on, the share with more pizza gets less crust.

The example cuts a pizza of 30 cm through a point off its center, checks that eight slices share the pizza and its crust equally wherever the point lies, and checks the rules of Mabry and Deiermann for one to eight cuts.

This page is part of a collection of geometry and design examples using planex2d.

A salami pizza cut through a point off its center into eight slices

[1]:
import math

import numpy as np
import planex as px

The slices

The pizza is a disc of radius \(R\) = 150, in millimeters. A slice between two neighboring cuts through the point \(P\) is the pizza intersected with a wedge from \(P\) that reaches past the pizza’s edge. The crust of a slice is the part of the pizza’s edge that it gets. It is the only arc among the slice’s edges, so crust adds up the lengths of the arc edges. Figure 1 shows the pizza cut two to five times through the point (55, 35):

[3]:
R = 150
pizza = px.Circle((0, 0), R).Face()


def slices(P, N, start=10):
    """the 2N slices of N cuts through P at equal angles, the first cut at start degrees"""
    found = []
    for k in range(2 * N):
        angles = [math.radians(start + 180 * (k + f) / N) for f in (0, 0.5, 1)]
        wedge = px.FromPolyline([P] + [(P[0] + 4 * R * math.cos(t), P[1] + 4 * R * math.sin(t)) for t in angles],
                                closed=True).Face()
        found.append(pizza * wedge)
    return found


def crust(piece):
    """the length of the pizza's edge that a slice gets"""
    return sum(e.mass for e in piece.edges if isinstance(e.edge, px.ArcEdge))


P = (55, 35)
cut = slices(P, 4)
print("areas", [round(s.mass) for s in cut], "| sum", sum(s.mass for s in cut), "| pizza", pizza.mass)
# px.Plot(px.Compound(cut))
areas [2889, 3776, 7337, 13901, 17788, 13892, 7330, 3774] | sum 70685.83470577034 | pizza 70685.83470577035
2 cuts
(a) 2 cuts
3 cuts
(b) 3 cuts
4 cuts
(c) 4 cuts
5 cuts
(d) 5 cuts
Figure 1: A pizza cut through the point P, the red cross, with its center as a blue dot and one share shaded

Eight slices

With four cuts, the eight slices alternate between two people. Wherever the point lies and whatever the angle of the first cut, each share is half the pizza, and each crust is half the edge, \(\pi R\) = 471.24 mm:

[5]:
rng = np.random.default_rng(1)
for _ in range(5):
    r, t = R * math.sqrt(rng.random()), 2 * math.pi * rng.random()
    P = (r * math.cos(t), r * math.sin(t))
    cut = slices(P, 4, start=360 * rng.random())
    one, other = cut[::2], cut[1::2]
    print("P", np.round(P, 1), "| pizza", sum(s.mass for s in one), sum(s.mass for s in other),
          "| crust", sum(map(crust, one)), sum(map(crust, other)))
P [102.2 -32.9] | pizza 35342.91735288518 35342.91735288518 | crust 471.23889803846896 471.2388980384689
P [-55.3 135.2] | pizza 35342.917352885175 35342.91735288517 | crust 471.23889803846896 471.23889803846885
P [-114.9   73.7] | pizza 35342.917352885175 35342.917352885175 | crust 471.23889803846896 471.238898038469
P [  0.5 -24.9] | pizza 35342.91735288514 35342.91735288518 | crust 471.2388980384686 471.2388980384691
P [ 20.6 -83.6] | pizza 35342.917352885175 35342.917352885146 | crust 471.23889803846896 471.23889803846873

Other numbers of cuts

For one to eight cuts through the point (55, 35), the share that holds the center is compared with the other one. Contains finds the slice that holds the center. Each line ends with what Mabry and Deiermann predict for the pizza, and the crust follows the last of their rules above:

[6]:
P = (55, 35)
for N in range(1, 9):
    cut = slices(P, N)
    k = next(k for k, s in enumerate(cut) if s.Contains((0, 0)))
    mine, other = cut[k % 2::2], cut[(k + 1) % 2::2]
    pizza_more = sum(s.mass for s in mine) - sum(s.mass for s in other)
    crust_more = sum(map(crust, mine)) - sum(map(crust, other))
    if N % 2 == 0 and N >= 4:
        predicted = "equal shares"
    elif N in (1, 2) or N % 4 == 3:
        predicted = "more for the center's share"
    else:
        predicted = "less for the center's share"
    print("cuts", N, "| the center's share minus the other's, pizza", round(100 * pizza_more / pizza.mass, 4), "%",
          "| crust", round(crust_more, 6), "mm | predicted", predicted)
cuts 1 | the center's share minus the other's, pizza 21.0531 % | crust 100.134675 mm | predicted more for the center's share
cuts 2 | the center's share minus the other's, pizza 8.4944 % | crust -0.0 mm | predicted more for the center's share
cuts 3 | the center's share minus the other's, pizza 1.2524 % | crust -6.3708 mm | predicted more for the center's share
cuts 4 | the center's share minus the other's, pizza -0.0 % | crust 0.0 mm | predicted equal shares
cuts 5 | the center's share minus the other's, pizza -0.0162 % | crust 0.249153 mm | predicted less for the center's share
cuts 6 | the center's share minus the other's, pizza -0.0 % | crust -0.0 mm | predicted equal shares
cuts 7 | the center's share minus the other's, pizza 0.0002 % | crust -0.00452 mm | predicted more for the center's share
cuts 8 | the center's share minus the other's, pizza 0.0 % | crust 0.0 mm | predicted equal shares

See Two faces for the intersection that makes each slice, and Kepler’s second law for sectors of equal area in an ellipse.