The June issue of Scientific American has an article on Sudoku, the number grid filling-in game that has swept the puzzle world. (Personally, I find the puzzles tedious, but to each their own.) As a programming exercise for myself, I put together a python Sudoku class to solve a Sudoku problem. It uses a simple backtracking algorithm, summarized below:
Given a valid starting position, for each row, each column and each 3 by 3 sub-matrix, construct a set of allowable entries; these are those numbers that are not yet included in the row (column, sub-matrix). To solve the problem, call the function Fill() on the upper-left cell of the matrix:
Fill (cell):
If the matrix is filled then we have a solution: print it and return
If the cell is not empty, go to the next cell (move left to right, top to bottom)
Else:
find the intersection of the allowable sets for the corresponding row, column and sub-matrix
for each entry in the intersection
place the entry in the matrix, delete that entry from the corresponding sets of allowable entries for the row, column and sub-matrix
call Fill on the next cell
remove the entry from the matrix, add the entry to the corresponding sets of allowable entries for the row, column and sub-matrix
Some comments on the code:
- I've done very little error-checking; here's hoping that strange data doesn't sneak in.
- Solutions can be found very quickly, though when no solutions are possible, the running time can be a couple of seconds. I've not made any attempt at optimizing the code; there may be special tricks that will speed up the process.
- The code could be modified for larger matrices (say, 16 by 16). However, since solving Sudoku problems is known to be NP-Complete, this kind of backtracking approach will not scale well.
- Two other approaches mentioned in the Wikipedia article are using Knuth's Dancing Links (after modeling the problem as a graph-coloring problem) and constraint programming. These would probably be better than the simple backtracking I used.