
Solving Every Sudoku Puzzle (2006) - Pete_D
https://norvig.com/sudoku.html
======
yeldarb
Sudoku solvers are near and dear to my heart.

They’re my go to problem when learning a new programming language because
they’re just complex enough to exercise a whole bunch of different language
features.

I built this when I wanted to learn Swift and dip my toe into machine
learning:
[https://twitter.com/braddwyer/status/910030265006923776?s=21](https://twitter.com/braddwyer/status/910030265006923776?s=21)

~~~
glenvdb
I know someone who likes to create a fractal generator when learning a new
language. He says it gives you a bit of exposure to the strengths of quirks in
the language from implementing algorithms, working with data structures, and
displaying a GUI to render an image to screen.

~~~
sdenton4
My go-to is the first fifty problems on Project Euler. It ramps up quite
nicely from "can you write a for loop?" to problems with some nice complexity.
Great for learning a language!

------
jedberg
An oldie but a goodie.

The other day we were at a restaurant and they gave my four year old a kids
menu. One of the activities was a modified sudoku that went up to 6. My first
thought was that I'd never realized you could do sudokus with other values of
N.

But the really cool part was that once I taught her the rules (the
constraints) she was actually able to figure it out without much help at all!

Turns out sudoku is a good way to teach kids logic, even at four years old.

~~~
rurp
You might want to check out KenKen puzzles. They are similar to Sudoku and
were created by a math teacher as a fun learning tool. IMO, they are quite a
bit more interesting than Sudoku puzzles.

~~~
antod
As well as Kenken, I also like Killer Sudoku as a more interesting option than
vanilla Sudoku. It's basically 9x9 Kenken with addition as the only operator,
it uses a bunch of the same thought processes as Kakuro which I like too.

------
war1025
Wrote a solver using basically the same idea back in college. Was kind of fun.
Probably some stupid things in there that I would do differently now with more
experience.

[https://github.com/war1025/sudoku-
solver/blob/master/Sudoku/...](https://github.com/war1025/sudoku-
solver/blob/master/Sudoku/Sudoku.vala)

~~~
lostcolony
Same. Didn't save the code; wish I had just so I could see if I got a better
execution time than his 1439 second example.

Amusingly, my rationale was much like the author's; I freakin' hate Sudoku. So
the fact it's such an obvious candidate to have an automated solver for meant
I wrote one (it was also an excuse to do something more meaningful than the
intro to CS exercises that class had me doing).

~~~
war1025
I left my solver running for 28 minutes and it never found a solution to that
puzzle. Guess whatever corner case it's hitting in his program is the same as
my program runs into.

~~~
mxz3000
Hmm it's weird. I tried my solver on it and it tells me that it can't find a
solution (in 13 seconds). My solver is pretty well tested (on some very
difficult sudokus as well). Maybe this guy's solver is bugged?

~~~
barbegal
It's trivial to know that it has more than one possible solution since less
than 8 of the possible numbers are on the initial board meaning any valid
solution that is found has a mirrored solution with all of one number swapped
for all of another number.

~~~
war1025
Theoretically a board with multiple solutions should be easier to find a
solution for though, right?

~~~
whataboutist
Theoretically a board with multiple solutions isn't a sudoku.

------
jhncls
I love it how with the Z3Py solver you just write down a few constraints
(rows, columns, 3x3 boxes and the given values) and you immediately get an
answer.

[0] [https://ericpony.github.io/z3py-tutorial/guide-
examples.htm](https://ericpony.github.io/z3py-tutorial/guide-examples.htm)

[1]
[https://yurichev.com/writings/SAT_SMT_by_example.pdf](https://yurichev.com/writings/SAT_SMT_by_example.pdf)

~~~
bgilroy26
Raymond Hettinger has a great video introduction to SAT solvers in python
[47m]

[https://www.youtube.com/watch?v=_GP9OpZPUYc](https://www.youtube.com/watch?v=_GP9OpZPUYc)

------
dang
A thread from 2015:
[https://news.ycombinator.com/item?id=9901214](https://news.ycombinator.com/item?id=9901214)

2011:
[https://news.ycombinator.com/item?id=3096922](https://news.ycombinator.com/item?id=3096922)

------
skizm
The key insight when writing a sudoku solver is that it is just depth first
search. Once someone told me that it just sort of clicked. Just guess each
possible number at each open square and if you ever get to an un-solvable
state, just undo the last change you made and try the next one. I was
extremely satisfied with myself after writing my first really clean solver
with backtracking.

I'm sure there are other, more efficient, ways to write sudoku solvers, but
the simplicity and clarity the DFS solver offers is pretty cool IMO.

~~~
jkaptur
I don't think there are, actually. Some algorithms might run faster in
practice, but, since the game is NP-complete, brute force is pretty much as
good as it gets for exact solutions.

~~~
war1025
The constraint propagation bit is the main key. It still ends up being a DFS,
but at most steps along the way, finding one number leads causally to several
other spaces being found.

In most easy / medium puzzles, there are actually no points where you need to
guess (i.e. recurse down the tree).

In many hard puzzles, there are only one of two guesses, which is where you
would recurse down the decision tree.

Things get a bit more intense once you move into the puzzles specifically
designed to be a pain in the neck for programs, but often those inputs aren't
actually valid Sudoku puzzles.

------
RcouF1uZ4gsC
Contrast this with the TDD approach:
[http://ravimohan.blogspot.com/2007/04/learning-from-
sudoku-s...](http://ravimohan.blogspot.com/2007/04/learning-from-sudoku-
solvers.html)

~~~
mannykannot
Do you mean the series of posts linked to from the one you give, beginning
with [1]? They are an excellent demonstration of two of the pitfalls of naive
TDD:

1) The things you can test first (before you have figured out the central
problem) are not necessarily the things that matter most. The author should
have addressed the algorithm for solving the puzzle first; everything else is
secondary.

2) This is an example of those cases where having tests for what you are going
to write does not provide much guidance into how to solve the problem.

[1]
[https://ronjeffries.com/xprog/articles/oksudoku/](https://ronjeffries.com/xprog/articles/oksudoku/)

~~~
dws
When making this comparison, it's worth noting that Jeffries is showing his
work process. Norvig is showing a cleaned up version of his final result after
throwing away some earlier attempts. (Source: I spoke with Peter about Sudoku
solvers shortly after he'd published.)

~~~
the_af
I think that's understood. But what's telling is that no single step of
Jeffries' series of articles seems to be approaching any kind of sensible
solution. It reads like an amateur -- e.g. me -- trying to write a game and
getting stuck in the low hanging but inconsequential fruit.

Because Jeffries' series is about TDD, and not really Sudoku, the _process_ is
important. And the process failed him spectacularly.

------
jessegee
I love the quote near the bottom: "Sudoku is a denial of service attack on
human intellect."

You could substitute "Sudoku" with most social media platforms and it would be
equally true. ;)

~~~
ernesth
Similar to how tetris was (jokingly ?) described as a plot of the soviet to
ruin the productivity of the west by hijacking the minds.

Second-hand Reference: [https://www.filfre.net/2017/06/a-tale-of-the-mirror-
world-pa...](https://www.filfre.net/2017/06/a-tale-of-the-mirror-world-
part-3-a-game-of-falling-shapes/)

------
Stenzel
Much faster if constraints are represented by single bits in an integer mask
and binary masking operations are used - even the hardest soduko solves
instantly.

------
foobaw
My first ever CS assignment was to build a sudoku solver using MIPS. I
remember reading this then and being inspired by the beauty of computer
science!

------
makomk
This is pretty much exactly the algorithm that
[https://www.ioccc.org/2005/aidan/aidan.c](https://www.ioccc.org/2005/aidan/aidan.c)
uses, except obviously much more clearly expressed. There's also a reasonably
straightforward extension of this technique that can test for solution
uniqueness, and so generate random valid puzzles; I can't remember how it was
implemented exactly but it involves continuing the search after finding the
first solution and seeing if it succeeds.

------
elquimico
I wrote a TypeScript implementation of this algorithm
[https://www.khrapov.org/sudoku/solver.html](https://www.khrapov.org/sudoku/solver.html)

------
pdonis
I always thought one of the requirements for published Sudoku puzzles was that
no trial and error should be required; it should be possible to deduce the
single unique solution from the clues given. This would mean the "search" part
of Norvig's algorithm would not be required; constraint propagation alone
would be enough.

~~~
l_t
I think technically, if constraint propagation can't solve the puzzle, that
means it's either contradictory (zero solutions) or ambiguous (multiple
solutions).

However, it seems Norvig was feeding his program with all three types of
puzzles -- zero, one, _and_ multiple solutions -- so perhaps that led him to
implement a more robust search.

~~~
T-hawk
If there is one unique solution, then constraint propagation always works,
yes.

But a propagated constraint isn't always just a single value at a time. There
are cases where a solver (human or machine) needs to identify that a group of
two or three or more cells mutually creates a constraint. ("Naked twins" and
other such configurations, in Sudoku jargon.) Which can recursively cause to
exist another such mutual constraint, and so on. Identifying every possible
way such a constraint can arise isn't a simple operation either to implement
or to execute, computationally speaking.

For both Norvig's programmatic solver and for a human, it's possible and
common for trial and error to be faster and more expedient than trying to
identify and execute every possible means a constraint can arise. Norvig's aim
was for implementational simplicity more so than computational elegance,
deciding to care about only the simplest possible type of constraint, and let
trial and error handle everything else.

------
carapace
FWIW, here's what I call "Boring Sudoku" in Prolog.

It is just 81 vars constrained to be 1..9 and then twenty-seven applications
of the Pigeonhole principle.

[https://swish.swi-prolog.org/p/Boring%20Sudoku.swinb](https://swish.swi-
prolog.org/p/Boring%20Sudoku.swinb)

------
catpolice
A while back I wrote a solver that uses no backtracking, just constraint
propagation, and it wasn't substantially more complex than this.

One of the key insights comes from noticing a feature of groups of numbers in
cells. For example, suppose you notice two cells in a given row and they're
the only cells in that row that the numbers 1 and 2 can be placed in - then
one of them is going to have 1 and the other will have 2, and you don't know
which but you can eliminate any other possibilities in those two cells. This
generalizes to groups of any size in rows/columns/squares. I think that and
maybe one other heuristic along with the basic rules about number placement is
enough to solve everything.

~~~
53x15
This sounds like Crook's Algorithm
([https://www.ams.org/notices/200904/tx090400460p.pdf](https://www.ams.org/notices/200904/tx090400460p.pdf)),
which is a perfectly reasonable thing to do, especially for pencil-and-paper
puzzle solving since pigeonhole inferences are easy for people to spot. But
this inference rule does not suffice on its own for many hard puzzles. Crook's
algorithm still requires backtracking.

------
gopalv
> I can copy values with values.copy() which is simple and efficient. If I
> implemented a possibility as a Python set or list I would need to use
> copy.deepcopy(values), which is less efficient.

The array deepcopy isn't too bad, at least when writing code, it compressed
into a neat slice [:]

I wrote a hinter[2] which was more fun than the actual solver too, because it
shows the "minimum remaining values" as a colour coded chart.

[1] -
[http://notmysock.org/code/sudoku/solver.py](http://notmysock.org/code/sudoku/solver.py)

[2] - [http://notmysock.org/code/sudoku/](http://notmysock.org/code/sudoku/)

------
pge
On a related note, Knuth has a cool algorithm to solve exact coverage problems
like sudoku (similar logic as Norvig's DFS but implemented very differently).
It's more work to code it than Norvig's but worth it for the education:) (and
it solves faster)

Here's the paper describing the algorithm:
[https://arxiv.org/pdf/cs/0011047.pdf](https://arxiv.org/pdf/cs/0011047.pdf)

~~~
CJefferson
While dancing links is cool, when benchmarking it turns out using bits to
represent values, and just copying, ends up being faster. This is because on
modern CPUs about the worst thing you can do is lots of pointer following.

~~~
tdons
I wrote a (straightforward) dancing links implementation that solves 17.000
puzzles/sec/core. It also validates uniqueness of the found solution.

How much faster does it get? I'm genuinely curious

~~~
emerent
There is a collection of benchmarks of the fastest sudoku solvers here:
[https://github.com/t-dillon/tdoku/tree/master/benchmarks](https://github.com/t-dillon/tdoku/tree/master/benchmarks)

How fast they are depends on the difficulty of the sudoku and on your machine,
but it's typically a few thousand/s on the hardest known and several 100k/s to
a million/s on very easy.

~~~
53x15
I'm the author of Tdoku and maintainer of those benchmarks.

If anyone has a well optimized DLX implementation I'd love to add it to the
comparison. The few I've sampled from github were not competitive, but I have
no idea how much effort when into them.

This page from 2011 has some comparisons of backtracking and DLX solvers from
that era, but it would be interesting to update:
[https://attractivechaos.wordpress.com/2011/06/19/an-
incomple...](https://attractivechaos.wordpress.com/2011/06/19/an-incomplete-
review-of-sudoku-solver-implementations/)

~~~
OskarS
Seems pretty competitive to me if the third fastest in your benchmark uses
dancing links.

I do think it's probably true that dancing links wont be literally the
fastest, but the neat thing is that it's a generic algorithm that solves ALL
total cover problems, not just Sudoku. Of course a tuned Sudoku solver could
probably beat it (optimizing around the Sudoku-specific parts), but it's nice
to see that it's at least in the running.

~~~
53x15
Bear in mind that JSolve was 5x faster than the fastest DLX solver in the
attractivechaos 2011 benchmarks, and today there are several solvers that are
2x faster than JSolve
([https://github.com/t-dillon/tdoku/tree/master/benchmarks](https://github.com/t-dillon/tdoku/tree/master/benchmarks)).
If the difference is really an order of magnitude, that's pretty non-
competitive.

I certainly don't mean do disparage DLX. It's a powerful and general
algorithm. But if you need a fast Sudoku solver (for puzzle mining or studying
Sudoku research questions) then it's not the tool I'd reach for. The
backtracking solvers just get a lot of mileage out of tuning their
representation to play nicely with hardware. They also blow general purpose
CDCL SAT solvers out of the water, at least for 9x9 Sudoku.

------
dahart
> As computer security expert Ben Laurie has stated, Sudoku is "a denial of
> service attack on human intellect". Several people I know (including my
> wife) were infected by the virus, and I thought maybe this would demonstrate
> that they didn't need to spend any more time on Sudoku.

That's hilarious! But what puzzles, or even activities wouldn't be classified
by Ben as a DOS on humans?

~~~
drcode
What I wonder is: In what way is chess different from sudoku that it is not a
DOS?

~~~
billforsternz
There's beauty in chess.

------
jazzychad
For a mind-melting good time, check out this sudoku solver written in APL:
[https://www.youtube.com/watch?v=DmT80OseAGs](https://www.youtube.com/watch?v=DmT80OseAGs)

------
billpg
I'd like to see a solver that works in a similar way to how a human would
solve a puzzle.

"This square must be a 5 because a 5 can't appear in any other cell in this
row."

~~~
Tehdasi
The algo described in the 'constraint propigation' section was basically how I
implemented my sodoku solver, and it basically can do 99% of all puzzles
thrown at it. And it wasn't particularly complicated.

------
jmpman
First time I saw a sudoku, was so intrigued, I wrote a solver using simulated
annealing. Solved any puzzle in a couple second.

------
mrcactu5
last year's US Sudoku Team Qualifier was held online at some point. Possibly
in May or July.

[http://wpc.puzzles.com/ussq2019/](http://wpc.puzzles.com/ussq2019/)

------
drudru11
A lot of people here have built solvers. What about Sudoku generators?

~~~
shagie
[https://sites.math.washington.edu/~morrow/mcm/team2280.pdf](https://sites.math.washington.edu/~morrow/mcm/team2280.pdf)
Is my favorite paper on the subject. Section 8.3 describes a generator.

~~~
drudru11
Awesome - thx!

