views:

248

answers:

3

An implementation of a brute-force algorithm to solve Sudoku puzzles fails if a cell is discovered in which placing any of the digits 1-9 would be an illegal move.

The implementation is written in C, with the board represented by a 9x9 array. The solver counts down from 9 until a legal number's reached, and if none can be reached, it outputs a zero in its place.

A zero also represents a cell to be filled in. Here's the output (truncated) if a string of zeros (an empty board) is the input:

9 8 7 6 5 4 3 2 1
6 5 4 9 8 7 0 0 0

Those last three zeros are there because the values filled in previously aren't changing. How can I stop the solver from failing like this?

+2  A: 

If you would currently put a zero in a spot, instead go back to the previous spot you put a number in and continue to count down till you find another value number for that spot.

For instance, in your example:

9 8 7 6 5 4 3 2 1
6 5 4 9 8 7 0 0 0

Instead of putting the zero in below the three, you would instead go back and try putting a 6 in below the 4.

Amber
OP: Yep, backtracking is what you want, and this is how you implement it.
torak
Well, if I do that, the 7 changes to a 3 and the following 0 remains, but the last 0 becomes a 7. The program just modifies the cell that was last changed.
Yktula
Is it the fault of cells that came before ?
Yktula
When you go back to a previous cell, you then need to start your filling from the cell after that - if you backtrack, you then have to start working forward again from right after where you backtracked to.
Amber
How do I know where to backtrack to ? Anything other than just changing previous cells and seeing if the ones that were zeroed can start to change ?
Yktula
Since your algorithm appears to work left-to-right, to-to-bottom, you should always backtrack to the previous cell (left, unless at the beginning of a row, then up to the rightmost of the previous row). If that cell has no more remaining valid numbers, then you backtrack another cell, and so on until you find one with a a remaining number.
Amber
How do you suggest I keep track of which cells are mutable (i.e., initially zeros) ? The algorithm does work the way you indicated; it simply iterates through the cells and changes ones valued at zero.
Yktula
I'd say you might want to keep a separate array which is the "original" state of the board (and is never modified), and check against that.
Amber
A: 

don't treat every "move" like the right move. E.g. placing the last 7 seemed ok but makes it so that in the next cell no valid moves are left. So upon hitting the "no move possible" situation, go back, and try the next option. Iterate and you will have your solution.

A better way of course would be to start brute forcing for places with a small set of options left; run through all cells and start brute forcing with the cell with the least number of options left. When starting out with all-zero, you would then end up with

9 8 7 6 5 4 3 2 1
6 5 4 0 0 0 0 0 0
3 2 1 0 0 0 0 0 0

which is legal, without backtracking once.

mvds
+1  A: 

You can do this by pushing your guesses onto a stack. Every time you end up wanting to output a zero, instead pop your last answer off the board and continue counting from it.

So if you guess 3 in (2,3) and next you're looking at (3,3) and get to zero, go back to (2,3) and try 2, then 1, then pop to before your (2,3) guess, etc.

Nathon
So, keep every working cell value on the stack, every working guess, or replace my multi-dimentional array (representing the cells) with a stack?
Yktula
The easiest way is probably to keep the guesses on the stack. You'll want to keep your 2-D array around so you can easily get an idea of what the legal values for your current cell are.
Nathon