last updated: 24 March 2007
This C code solves 9x9 sudoku puzzles using "logic" not "brute force". Considering how small a problem sudoku puzzles are with modern computer speeds and memory, "brute force" is a very suitable approach even if it does lack a degree of elegance. After finishing this code, a google search of of "+sudoku +solver" revealed a link to a 3 line perl solver (actually, 20 lines formatted). Yes, that did use brute force... but doing so in 3 lines of code is remarkably elegant.
When I was young, back in the day when I could multiply multi-digit numbers, add columns, or divide in my head, I would have been able to train my mind to solve most sudoku with almost no pencil work. Not so any more: too much clutter in my head and too many brain cells out-to-lunch or in semi-retirement (or just plain dead). Doing puzzles by pencil is good mental exercise and I may continue to do them to exercise those brain cells which are still responding, but I soon realized there are other (not really "better") ways. Besides, opportunity to write code, even for computer professionals, is rather rare and in the writing is a bit of artistry. Geeks do these things because they must (like other artists). Opportunity presented itself when I went on two week sick leave.
First hand Sudoku done 01/2006 (introduced to me by my wife). Did probably 30ish puzzles (mostly from newspaper, some from Will Shortz book). Initially, took 30-60 minutes to solve a newspaper puzzle and I would not attempt anything beyond 3 stars. By time program started (2006-01-31), had done both 4 and 5 star puzzles by hand (30-60 minutes each, down to 10ish minutes for 1 or 2 star).
01/31 2hr Design on paper (in outpatient waiting room)
2hr Initial write (initialization and structure)
02/01 2hr Basic solver written
02/02 2hr Level2 solver written
2hr Debugging and initial fluff added
02/03 2hr Level3 solver written, most examples solvable
02/04 4hr Rewrite Level2|3 as generic Masker after found
an example requiring a Level4 solver.
02/05 3hr Additional testing/debugging/fluff and code restructures
02/06 3hr Code cleanup and documentation writtten
02/07 3hr Brute force solver for non-unique puzzles
02/08 3hr Add to uak kit (man page and html, timing examples)
02/09 1hr Pretty-up the format for initial/resolved
----- Time to design, write, test, re-write, document
29hrs
This might make a good programming course problem.
Young minds should be able to write this quicker, provided they can comfortably/fluently write C.
Note, a functional solver was available in 12 hours.
Some fluff already included by then and more added.
Writen on Mac OSX, code should work "as is" on Linux or any UNIX variant. Tested on Irix and AIX.
For the 3 line perl brute force solver see Edmund von der Burg's blog:
http://www.ecclestoad.co.uk/blog/2005/06/02/sudoku_solver_in_three_lines_explained.htmlThe "brute forces" is a bit slower to execute than using logic, but it works.
sudoku.c, logic perl, brute | sudoku.c, logic perl, brute
Elapsed CPU Elapsed CPU | Elapsed CPU Elapsed CPU
Example ------- --- ------- --- | ------- --- ------- ---
#1: 0.02 0.00 2.63 2.60 | 0.01 0.00 2.04 1.76
#2: 0.01 0.00 18.49 18.44 | 0.01 0.00 13.31 12.20
#3: 0.01 0.00 3:29.02 3:28.98 | 0.01 0.00 2:30.29 2:20.03
#4: 0.01 0.00 3.29 3.26 | 0.01 0.01 2.45 2.20
#5: 0.01 0.00 1:50.63 1:50.58 | 0.01 0.00 1:19.72 1:12.93
#6: 0.00 0.00 10.12 10.06 | 0.01 0.00 7.02 6.47
#7: 0.00 0.00 22.24 22.16 | 0.01 0.00 15.38 14.20
#8: 0.02 0.01 0.63 0.59 | 0.02 0.02 0.50 0.39
#9: 0.01 0.00 0.14 0.10 | 0.01 0.00 0.09 0.07
|
System: IBM p650 1.1ghz running AIX 5.2 | MacOSX 10.4.3 PowerPC G4 1.5ghz
As expected, for a non-unique puzzle the brute-force sudoku.perl script stops on
the first match (example #8) while sudoku.c generates two possible solutions.
Both successfully detect an invalid puzzle (example #9), sudoku.prl exits
quietly while sudoku.c reports when it found the problem.
iceberg2: sudoku -example 3
_Pocket Sudoku_ Volume 3, #145 (Will Shortz)
Level -1 Known 22, Unknown 59, Solved 0, Errors 0
+---------------+---------------+---------------+
| (2) (1) . | . . . | . . . |
| . . . | . . (3) | (1) . . |
| . . (9) | (4) . . | . . (7) |
+---------------+---------------+---------------+
| (8) (2) (5) | . . (4) | . . . |
| . . . | (6) . . | . . . |
| (1) . . | . . (8) | (2) . . |
+---------------+---------------+---------------+
| . (7) . | . (9) . | . . . |
| . . . | . (3) (1) | . (4) . |
| . . . | . . . | (3) (8) . |
+---------------+---------------+---------------+
_Pocket Sudoku_ Volume 3, #145 (Will Shortz)
Level 3 Known 22, Unknown 0, Solved 59, Errors 0
+---------------+---------------+---------------+
| (2) (1) 8 | 9 6 7 | 4 3 5 |
| 5 4 7 | 2 8 (3) | (1) 9 6 |
| 3 6 (9) | (4) 1 5 | 8 2 (7) |
+---------------+---------------+---------------+
| (8) (2) (5) | 1 7 (4) | 9 6 3 |
| 7 3 4 | (6) 2 9 | 5 1 8 |
| (1) 9 6 | 3 5 (8) | (2) 7 4 |
+---------------+---------------+---------------+
| 4 (7) 3 | 8 (9) 2 | 6 5 1 |
| 6 8 2 | 5 (3) (1) | 7 (4) 9 |
| 9 5 1 | 7 4 6 | (3) (8) 2 |
+---------------+---------------+---------------+
iceberg2: sudoku -help
sudoku # sudoku v2.1
-h this usage information
-e N where N is one of 17 internal examples
-f list of internal examples
-b B where B is number unique solutions when brute invoked
(defaults as 2)
-l L where L is level to start solving (1 to 8)
-m M where M is maximum level to mask, maximum 8
-s S show level (bit mask), default 0, where:
0 initial/results only
1 possible values
2 eliminated values
4 octal mask (possible)
-i show initial only
-p show progress to solution
-q quiet option
-v verbose option
-z output progress in perl brute format
The puzzle is read from stdin in 9 rows of 9 numbers,
unless '-example N' is specfied for a pre-built example.
Use 0 (or any of: '.*x') for a missing value.
Use a space, any other punctuation, or nothing delimit values.
End of Story