Sudoku is one of my long-time favorite game for killing time in a flight or idly waiting something. It tests memory and deduction. More importantly, it is fun to play.

The original thought of solving it comes from the Algorithm Design Manual and its wiki page. However, the backtracking algorithm provided in both places are somewhat obscure. Specifically for the backtracking solution, the algorithm is:

By exploring every possible solution, it actually performs a depth-first search. But as a typical backtracking implementation, a proper pruning has a greater impact on search time than any other factor. Specifically, a pruning strategy requires carefully ordering the evaluations of the pieces. In this implementation, it means that the algorithm needs to decide evaluating which empty slot. Obviously, in a given stage, evaluating a slot with only three candidates takes only 1/3 search spacing comparing with a slot with nine candidates.

I use the basic rules of Sudoku to eliminate candidates:

- If a square has only one possible value, then eliminate that value from the squareâ€™s peers (same line, same column, and same zone).
- If a unit has only one possible place for a value, then put the value there.

Each iteration of backtracking possesses its own information of both board and the available candidates for each currently empty slot. The algorithm only explore the slot with lest candidates, and whenever an empty slot is assigned a value, both information will be updated. This process is called *variables ordering* by Constraint Propagation.

Concerning the data types, it is tempting to use heap for the empty slots since the program is only interest in the slot with lest candidates. But since the constraints also needs to update in every iteration, and there are only 60+ empty slots at most. It is good enough to use a dictionary with coordinates as key and the candidates as values.

The two major functions are the Constraint Propagation:

, and the optimized main function:

The complete program can be found here.

It is nice to see the hardest puzzle solved in a second:) And how simple the original algorithm is for a seemly complicated problem.

cheers:)