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?

Yktula
  • 14,179
  • 14
  • 48
  • 71
  • 2
    maybe you have a bug in the implementation – rachvela Jul 23 '10 at 17:08
  • I feel that a brute-force solver is made obsolete and uninteresting by the existence of simple constraint solvers like the one by Peter Norvig (http://norvig.com/sudoku.html). – Svante Jul 24 '10 at 09:03

3 Answers3

2

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
  • 507,862
  • 82
  • 626
  • 550
  • OP: Yep, backtracking is what you want, and this is how you implement it. – torak Jul 23 '10 at 17:10
  • 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 Jul 23 '10 at 17:21
  • Is it the fault of cells that came before ? – Yktula Jul 23 '10 at 17:36
  • 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 Jul 23 '10 at 17:56
  • 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 Jul 23 '10 at 18:09
  • 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 Jul 23 '10 at 18:45
  • 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 Jul 23 '10 at 18:55
  • 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 Jul 23 '10 at 19:31
1

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
  • 45,755
  • 8
  • 102
  • 111
1

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.

nmichaels
  • 49,466
  • 12
  • 107
  • 135
  • 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 Jul 23 '10 at 17:50
  • 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. – nmichaels Jul 23 '10 at 19:18