Books · Solving Puzzles through Mathematical Programming
Chapter 10
Dobble
Dobble is a card game of fifty-five cards, each bearing eight pictorial symbols drawn from a pool of fifty-seven. It is marketed under the trade names Dobble in Europe and Spot It! in North America, and sold as a speed-matching game: players race to identify a symbol common to two cards. The design guarantees that this common symbol always exists and is always unique — any two cards in the deck share exactly one symbol. The combinatorial feat that makes the game playable conceals a piece of classical finite geometry: a full Dobble deck is a projective plane of order seven (projective planes exist for every prime-power order).
The deck’s parameters are not arbitrary. A projective plane of order has points and the same number of lines; each line passes through points, each point lies on lines, and any two distinct lines intersect in exactly one point. Setting gives symbols, cards, symbols per card, and the Dobble guarantee. (Commercial decks trim the full cards to for printing reasons; the mathematics works for any subset.) The existence of a plane of order is guaranteed when is a prime power, in which case the finite-field construction below applies. For (not a prime power) no plane exists, by the Bruck–Ryser theorem; for the nonexistence is a celebrated result of Lam, Thiel, and Swiercz ().
The Fano plane:
The smallest projective plane is the Fano plane, : points, lines, points per line. Figure 10.1 shows the standard picture: a triangle, its three medians, and an inscribed circle. The three sides, three medians, and one circle together make seven lines; the three vertices, three edge midpoints, and one centroid make seven points; and any two lines meet in exactly one point.
A “mini-Dobble” with the Fano plane’s parameters has seven cards, each with three symbols; any two share exactly one symbol. The seven cards are the seven lines of Figure 10.1: the three sides , , , each carrying its edge midpoint; the three medians , , , each through the centre ; and the inscribed circle through the three midpoints.
The programming model
Constructing a projective plane of a given order by pure search is an exact-cover-flavoured problem with a beautifully simple encoding.
Variables
For each card and each symbol (where ), introduce a Boolean variable : one if card contains symbol , zero otherwise.
Card size
Each card has exactly symbols:
Symbol multiplicity
Each symbol appears on exactly cards:
Pairwise intersection
For every pair of distinct cards , exactly one symbol is shared. Since is the indicator that symbol lies on both cards, the constraint is In CP-SAT the product is linearised by introducing an auxiliary Boolean and requiring .
Symmetry breaking
The full automorphism group of a projective plane is enormous, so without symmetry breaking the enumerator will revisit many equivalent decks. A common break fixes the contents of card : card . This pins the first card’s symbols and halves or more the search tree.
A solver in forty lines
from ortools.sat.python import cp_model
def dobble(n):
N = n * n + n + 1
m = cp_model.CpModel()
x = [[m.NewBoolVar("")
for _ in range(N)] for _ in range(N)]
# Each card has n+1 symbols
for i in range(N):
m.Add(sum(x[i][j]
for j in range(N)) == n + 1)
# Each symbol on n+1 cards
for j in range(N):
m.Add(sum(x[i][j]
for i in range(N)) == n + 1)
# Any two cards share exactly one symbol
for i in range(N):
for k in range(i + 1, N):
y = [m.NewBoolVar("") for _ in range(N)]
for j in range(N):
m.AddBoolAnd(
[x[i][j], x[k][j]]
).OnlyEnforceIf(y[j])
m.AddBoolOr(
[x[i][j].Not(), x[k][j].Not()]
).OnlyEnforceIf(y[j].Not())
m.Add(sum(y) == 1)
# Symmetry break: card 0 = {0, 1, ..., n}
for j in range(N):
m.Add(x[0][j] == (1 if j <= n else 0))
s = cp_model.CpSolver()
s.parameters.max_time_in_seconds = 120
s.Solve(m)
return [[j for j in range(N) if s.Value(x[i][j])]
for i in range(N)]
Timings (on a standard laptop, with the symmetry break above): No projective plane of order exists, by the Bruck–Ryser theorem, and the solver confirms this by eventually returning infeasible; note though that proving nonexistence is a genuine exhaustive search, far slower than finding a plane that does exist, so the time it takes is not the fraction of a second the feasible cases enjoy. For the model is beyond naive CP-SAT; the nonexistence result is Lam–Thiel–Swiercz’s theorem, obtained by a much larger specialised search.
The algebraic construction
For a prime power , the projective plane is built directly. Points are equivalence classes of under scaling; lines are the same, with the duality that point lies on line if and only if in the finite field . When is prime this is ordinary arithmetic modulo ; when is a proper prime power the field is needed, since the ring then has zero divisors and is not a field. For this assembles a full Dobble deck in microseconds, yielding the same incidence matrix that CP-SAT recovers by search (up to permutation of rows and columns).
Sources. Projective planes entered finite geometry in the late nineteenth century through the work of Karl von Staudt and Theodor Reye; the Fano plane is named after Gino Fano (). The classical existence theorem for planes of prime power order is due to Veblen and Wedderburn (). The Bruck–Ryser nonexistence theorem () rules out orders unless is a sum of two squares. The nonexistence for is due to Lam, Thiel, and Swiercz (Canadian Journal of Mathematics, ), a major computational result that occupied several Cray years. The Bruck–Ryser theorem also rules out orders and (neither is a sum of two squares, and both are ), so the smallest orders whose existence is currently open are . The mapping of finite projective planes to a physical game of cards has a longer history than the commercial product suggests: in the French enthusiast Jacques Cottereau devised an unpublished set of insect cards with the shared-symbol property, and in the game designer Denis Blanchot reworked the idea into Dobble, published in .