How we make sure every sudoku has one solution
The Once Books team · 1 October 2026 · 8 min read
A sudoku generator guarantees one solution by checking, not by construction. Our engine fills a complete 9 by 9 grid with a randomised backtracking search, then removes clues one symmetric pair at a time. After every single removal it re-solves the board with a solver that stops the moment it finds a second answer. If a second answer exists, the clue goes back. Nothing reaches a page unless the final board still solves exactly one way.
Those five sentences are the method. The rest of this post is the code behind each step, the numbers it produces, and the two places where our own comments turned out to be slightly optimistic.
How is the finished solution grid generated?
The solution comes first, as a full, rule-legal grid built by backtracking over a flat 81-cell array. Each row, column and 3 by 3 box keeps a 9-bit mask of the digits it already holds, so a cell's candidates are one bitwise expression:
const candidates = ~(rows[row]! | cols[col]! | boxes[boxOf(row, col)]!) & ALL_DIGITS_MASK;
The search always fills the empty cell with the fewest candidates first (the minimum-remaining-values heuristic, MRV), and it tries that cell's digits in a seeded-random order:
const digits: number[] = [];
for (let m = bestCandidates; m; m &= m - 1) {
const bit = m & -m;
digits.push(31 - Math.clz32(bit) + 1);
}
shuffle(digits, rng);
The randomness comes from a seeded Mulberry32 generator shared by every puzzle engine we ship. We don't use Math.random here, because a stored seed has to rebuild the same board in the worker, the studio preview and the free sudoku generator. On a 2.8 GHz Xeon under Node 22, one completed grid takes about 0.12 ms, averaged over 1,000 seeds.
How are clues removed without breaking uniqueness?
Clues come out one symmetric pair at a time, and each removal is kept only if the board still has one solution. The digger shuffles all 81 cell indexes, then walks them in that order. With symmetry on (the default), cell i is removed together with its 180-degree partner 80 - i, which gives the classic newspaper look:
const partner = symmetric ? CELL_COUNT - 1 - i : i;
const removing = partner === i ? 1 : givens[partner] !== 0 ? 2 : 1;
if (clues - removing < band.min) continue;
givens[i] = 0;
if (partner !== i) givens[partner] = 0;
if (hasUniqueSolution(givens)) {
clues -= removing;
} else {
givens[i] = savedI;
givens[partner] = savedPartner;
}
This is a greedy search. It never reconsiders a clue it kept, so where it stops depends on the order it happened to try cells in. To get closer to the target, the generator runs the dig up to 12 times from the same solution with different seeded orders (MAX_DIG_ATTEMPTS = 12) and keep the attempt closest to the target clue count. The loop exits early the moment one attempt reaches the target, so easy boards cost a single dig.
The payoff is measurable. Over 200 seeds, a single greedy dig aimed at Evil ended anywhere from 24 to 32 clues, most often at 28. Best-of-12 moved the typical result to 25.
How does the solver prove there's only one answer?
The uniqueness check is a solver that counts solutions but gives up counting at two. It uses the same bitmask and MRV approach as the grid builder, minus the randomness, and it stops the recursion as soon as the count reaches the cap:
export function hasUniqueSolution(grid: SudokuGrid): boolean {
return countSolutions(grid, 2) === 1;
}
The cap is what makes this affordable. You don't need to know whether a broken board has 2 solutions or 2,000; you only need to know it has more than one. On a finished 24-clue Evil board, one call takes about 0.06 ms in our measurement (2,000 calls averaged). The solver also rejects a board with a repeated digit before searching, so a malformed input returns zero solutions instead of a wrong answer.
Before a puzzle is marked valid, the generator runs the check one final time on the finished givens and confirms the clue count sits inside its grade's band:
const isValid = hasUniqueSolution(givens) && clueCount >= band.min && clueCount <= band.max;
A separate QA function, validateSudokuStructure, repeats this from the stored data: the solution must be a complete legal grid, every given must match the solution in its cell, the stored clue count must match the givens, and the givens must have exactly one solution. Our tests also re-solve each generated board and compare it cell by cell to the stored answer key, using a rule checker written separately from the engine so the engine can't pass by agreeing with itself.
How is difficulty graded?
Difficulty is graded purely by how many clues are left, against five fixed bands:
| Grade | Target clues | Floor (min) | Ceiling (max) |
|---|---|---|---|
| Easy | 42 | 38 | 52 |
| Medium | 34 | 30 | 44 |
| Hard | 30 | 27 | 38 |
| Extreme | 27 | 24 | 34 |
| Evil | 24 | 22 | 31 |
This is the trade-off we accepted, and the type file says so in its own comment: difficulty really depends on the solving techniques a board demands, but clue count is "the lever a dig-based generator actually controls". A technique-based grader would have to solve every board the way a person does (singles, pairs, X-wings and so on) and rate the hardest step. We haven't built that. The practical effect is that two Hard boards with 30 clues each can feel different to a solver, and nothing in the grader stops a board from needing a harder technique than its label suggests.
The floors are also set well above the mathematical limit. 17 clues is the proven minimum for a unique 9 by 9 sudoku, but a greedy dig that preserves uniqueness rarely gets below about 24, so the bands are calibrated to what the digger can reach rather than to the theory.
What does a board cost to generate?
A board costs well under a millisecond at the easy end and about 40 ms at Evil, and nearly all of that is uniqueness checks. We measured 200 seeds per grade on Node 22 (2.8 GHz Xeon):
| Grade | Mean time | 95th percentile | Uniqueness checks per board | Clue counts produced |
|---|---|---|---|---|
| Easy | 0.36 ms | 0.53 ms | 22 | 41 (147), 42 (53) |
| Medium | 0.82 ms | 2.59 ms | 28 | 33 (130), 34 (70) |
| Hard | 0.94 ms | 1.70 ms | 35 | 29 (109), 30 (91) |
| Extreme | 7.13 ms | 24.71 ms | 132 | 26 (42), 27 (156), 28 (2) |
| Evil | 40.22 ms | 66.00 ms | 560 | 23 to 27, most often 25 (83) |
All 1,000 boards passed the final check. A 100-puzzle book with 20 boards at each grade took between 0.95 and 1.19 seconds across three runs. In the product, books are generated in a background worker with an 8-minute timeout, and each board's valid flag is stored with it.
Where did the code and the comments disagree?
Two comments in the engine promise slightly more than the measurements show, and both are worth knowing if you build something similar.
The first is about Easy. The band comment says easy grades "hit their target on the nose". They land one under it about three times in four: 147 of 200 Easy boards finished at 41 clues, not 42. The cause is parity. A full grid has 81 cells, the centre cell is its own symmetric partner, and every other removal takes two cells. Until the centre goes, the count stays odd (81, 79, down to 43), and 43 is still above 42, so one more pair comes out and the board lands on 41. It's harmless, since 41 sits inside the 38 to 52 band, but it's a good example of an invariant nobody wrote down.
The second is Evil. The comment says best-of-12 reaches about 24 clues. In our run, 55 of 200 Evil boards reached 24 or fewer, and the most common result was 25. Every one of them was still unique and inside the 22 to 31 band, so none failed validation. The difference between the grades at the hard end is how close each sits to the digger's floor, and 12 attempts don't always get all the way there.
What the generator guarantees: every board it marks valid has exactly one solution, and the printed answer is that solution. What it doesn't claim: that two boards in the same grade need the same solving techniques.
Why keep the seed?
Every puzzle stores the seed that produced it, so the same seed rebuilds a byte-identical board. A book's puzzles are seeded from one base seed plus a fixed step per position, and the tests rebuild a whole book twice from seed 42 and compare every given and solution. That's what lets us re-export a book at a different trim, or reproduce a customer's exact board in a bug report, without storing anything more than a number.
Stored values outlive code, and the grade names taught us that too. Extreme used to be called Expert, and the old spelling is persisted on puzzle rows and difficulty mixes. A deploy is never atomic with its data migration, so the parser still maps EXPERT to EXTREME. Without that mapping, a row the migration hadn't reached would grade against the wrong band and print one difficulty star instead of four.
If you want to see a board come out of this exact code, the free sudoku generator runs the same engine in your browser and prints the puzzle with its solution. For a full graded book with a numbered solutions section, the KDP sudoku maker runs it in the worker, and the guide to making and selling sudoku books on KDP covers everything after the puzzles are built.
Try the tool
Free, in your browser, no sign-up. Make one, then build the whole book in the studio.
Questions parents ask
- How do you generate a sudoku with a unique solution?
- Start from a completed, rule-legal 9 by 9 grid, then remove clues one at a time (or in symmetric pairs). After each removal, run a solver that stops as soon as it finds a second solution. If it finds one, put the clue back. Every board that survives has exactly one answer.
- How do you check that a sudoku has only one solution?
- Count solutions with a backtracking solver capped at two. If the count is 1, the puzzle is unique; if it reaches 2, it isn't, and the solver stops right there instead of counting every solution. On our engine one check takes about 0.06 ms on a 24-clue board.
- What is the minimum number of clues for a sudoku to have one solution?
- 17 is the proven minimum for a standard 9 by 9 sudoku. Our generator never goes near it: the hardest grade aims for 24 clues and never removes below 22, because a greedy uniqueness-preserving dig rarely gets under about 24.
- How is sudoku difficulty graded by a generator?
- Ours grades by clue count only: Easy aims for 42 givens, Medium 34, Hard 30, Extreme 27 and Evil 24. It doesn't rate the solving techniques a board needs, so two puzzles with the same clue count can feel different to solve.
Related reading
KDP sudoku interior specs: trims, margins and solutions
The trim sizes, margins, gutter, bleed and solutions layout a KDP sudoku interior needs to pass review, with the large-print grid numbers that sell.
How to make and sell sudoku books on Amazon KDP
A practical 2026 guide to making sudoku books for Amazon KDP: a difficulty curve, single-solution grids, interior specs, a solutions section and upload.
Word search books for kids on KDP: what sells
How to make a kids word search book that sells on Amazon KDP: big grids, short familiar words, no diagonals, bright themes. The choices that fit a child.
Keep reading
Answers
One sharply-scoped question per page, cost, safety, timing, printing, answered in a couple of sentences before the detail.
Glossary
Plain definitions of the vocabulary: the Character Sheet, the Consistency Engine, style profiles, drift.
Help centre
Task-shaped instructions for making, printing and sharing a book once you have started one.