Your solution is pretty close to mine. If I understand your design (tell me if I'm wrong), your array is laid out such that indices {0..8} are the first horizontal row, {9..17} the second, and so forth.
It looks like your markValuePerRow uses recursion to remove the chosen random value from each cell within the row except the cell you are working on. This sounds right, though I'd just make it a for() loop instead of using recursion.
It looks like your markValuePerCol works in the same way as markValuePerRow.
You'll need a markValuePerBlock yet, which you already know.
So generally speaking our respective programs do the same things. In fact, we have many of the same functions:
Your function My function
markValuePerCol clear_bit_in_column
markValuePerRow clear_bit_in_row
coordinateXMaker optimized out, as it is a one-liner for me
coordinateYMaker optimized out, as it is a one-liner for me
randomGenerator this is part of my solve() function
main solve
main
get_nth_set_bit
I think that the problem with your program is that you need to backtrack. It is possible for
your program to get into a state where it cannot solve the puzzle. When that happens,
your randomGenerator function will never return causing an infinite loop. This is where
my recursive algorithm solves the problem.
That is, after I've assigned values to the first, say, 50 elements in the grid, if I find that
there is no possible value to put into the 51st element, my algorithm back tracks -- it
goes back to the 50th element and tries a different value instead of the first one it picked.
If again it finds that there is no possible value to put into the 51st element, it tries a
different value for the 50th element. If it runs out of values to try for the 50th element,
it goes back to the 49th element and tries a different value there. And the algorithm
continues.
This is where my recursion comes in. So my algorithm goes something like this:
bool solve( puzzle, element ) {
1. figure_out_possible_values_for_cell( puzzle, element );
2. randomly choose one value
3. put value in cell and mark rows, columns, and blocks
4. call solve( puzzle, element + 1 );
5. if it returned false, then remove from the possible values the value we picked
and go back to step 2. If there are no more possible values, then return
false.
}
Now I've left out a detail or two, and certainly this isn't the only way to solve the
problem. (And note, I do not use gotos).
I think the main reason why your code is twice as long as mine is that whereas
you use arrays I use STL containers. The containers are flexible and powerful
enough that I can often do in 1 line of code what takes you a couple to implement
a for loop.
For example, your code uses 3 lines of code to implement a nested for() loop to
initialize your data structure whereas I was able to initialize mine in 1 line of
code.
In fact, here is my main:
1 2 3 4
|
int main() {
srand( time( 0 ) );
solve( PuzzleBoard( 81, bitset<9>( string( 9, '1' ) ) ), 0 );
}
|
For me, PuzzleBoard is a vector< bitset<9> >. My vector is equivalent
to your cell[81], and bitset<9> is your values array inside cells_t.
Your code sets value[N] = N + 1 to indicate that N + 1 is a possible
value. My code sets bit N to indicate that N + 1 is a possible value.
So to understand my line of code:
string( 9, '1' )
creates a string of 9 '1's.
bitset<9>( string( 9, '1' ) )
creates the 9-bit value 1 1111 1111
which indicates all 9 values are possible.
vector( 81, bitset<9>( string( 9, '1' ) ) )
creates an array of 81
such 9-bit values to indicate that all 9 values are possible in all 81 cells.