I\'m trying to make a Sudoku Solving program for a couple of days but I\'m stuck with the methods. I found this algorithm here but I don\'t really understand it:
The following assumes you are trying to solve a given board, not generate a puzzle.
Create a class whose objects can hold a board (here called board_t
). This class may internally use array, but must support copying boards.
Have a function void solve(board_t const& board);
which repeats the following for each number n
:
n
in the first empty cell of the copied boardreturn
.solve(copied_board)
This is a recursive backtracking solution, which performs horribly for hard problems. You can significantly speed it up by proper pruning or deductive steps (e.g. if you end up with 8 numbers in a row after inserting one, you can immediately enter the ninth without any kind of search).
While certainly not an impressive technique, it has a high probability of working correctly, since you will only ever be modifying a copy to add a single value. This prevents corruption of your data structures (one problem your idea has is that it will destroy the numbers it finds when backtracking, are not necessarily the ones you just inserted, but may be part of the initial puzzle).
Improving performance is quite simple, once you start picking more intelligent heuristics (e.g. instead of testing the square in order, you could pick the ones with the fewest remaining moves and try to get them out of the way - or do the reverse...) or start doing a bit of deduction and pruning.
Note: The Algorithm Design Manual uses a Soduko solver to show the impact of these techniques on backtracking.
There is one very important modification to recursive algorithms: Use most constrained first approach. This means first to solve a cell with smallest number of possible candidates (when direct row/column/block conflicts are removed).
Another modification is: Change the board in-place; do not copy it. In each recursive call you modify only one cell on the board, and that cell used to be empty. If that call doesn't end up in a solved board somewhere down the recursive call tree, just clear the cell again before returning - this returns the board into original state.
You can find a very short and fast solution in C# on address: Sudoku Solver. It solves arbitrary sudoku board in about 100 steps only, all thanks to the most constrained first heuristic.
TNode
TNode => vector<TNode>
S
can have number N
added at row I
, column J
if:
(I,J)
is emptyN
in row I
N
in column J
N
in the 3x3 square containing (I,J)
S
to the vector
of states that satisfy these rulesYour current approach mixes the specification of the graph to be searched and the implementation of the search algorithm. You're going to have a lot of difficulty if you mix those two. This problem naturally separates into two distinct pieces -- the algorithm and the graph -- so you can and should exploit that in your implementation. It will make it much simpler.
The other benefit you get if you go with this separation is that you will be able to reuse your graph search algorithm on a huge number of problems - very cool!
This is a classic Constraint Satisfaction Problem. I recommend doing some research on the topic to figure out the successful strategy. You will need to use AC-3 ( Arc Consistency 3) algorithm along with the backtracking techniques to solve the problem.