|
|
|
Here is an example of a recursive Sudoku solver in C.
It performs the following steps:
In the program, the solve_matrix function is the core routine. In it, the a[9][9] array contains the original matrix as passed to it. The h (hold) array is used to make the requested selection (passed to the function as row, column, and digit). The p array contains bit-mapped "possibility" flags for each digit 1 through 9, set via the figure_possibles function. Let me know if further details are needed.
// SOLVE.C
// Solve a Sudoku puzzle
// Last revised 7 October 2006
#include <stdio.h>
#include <stdlib.h>
#define E_OK 0
#define E_BAD_ROW 1
#define E_BAD_COLUMN 2
#define E_ALREADY_SET 3
#define E_DONE 4
#define E_LACKING_POSSIBILITIES 5
int test_zero[9][9] = { 9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0 };
int test_one[9][9] = { 4, 0, 0, 0, 6, 0, 0, 0, 9,
0 ,0, 8, 7, 0, 5, 4, 0, 0,
0, 1, 0, 0, 0, 0, 0, 8, 0,
0, 7, 0, 0, 0, 0, 0, 4, 0,
2, 0, 0, 0, 8, 0, 0, 0, 1,
0, 8, 0, 0, 0, 0, 0, 3, 0,
0, 3, 0, 0, 0, 0, 0, 1, 0,
5, 0, 0, 0, 4, 0, 0, 0, 2 };
int test_two[9][9] = { 3, 0, 0, 0, 5, 0, 0, 0, 2,
0, 0, 5, 3, 0, 6, 7, 0, 0,
0, 8, 0, 0, 0, 0, 0, 3, 0,
0, 3, 0, 0, 0, 0, 0, 8, 0,
5, 0, 0, 0, 4, 0, 0, 0, 6,
0, 7, 0, 0, 0, 0, 0, 9, 0,
0, 9, 0, 0, 0, 0, 0, 2, 0,
0, 0, 3, 4, 0, 7, 9, 0, 0,
1, 0, 0, 0, 2, 0, 0, 0, 4 };
int w[9][9];
void zero_matrix( int a[9][9] )
{
int row, column;
for ( row = 0; row < 9; row++ )
for ( column = 0; column < 9; column++ )
a[row][column] = 0;
}
void set_possible( int p[9][9], int row, int column, int digit )
{
int mask;
mask = 1 << ( digit - 1 );
p[row][column] |= mask;
}
void set_impossible( int p[9][9], int row, int column, int digit )
{
int mask;
mask = 1 << ( digit - 1 );
p[row][column] &= ~mask;
}
int is_possible( int p[9][9], int row, int column, int digit )
{
int mask;
mask = 1 << ( digit - 1 );
if ( p[row][column] & mask )
return( 1 );
return ( 0 );
}
int count_possible( int p[9][9], int row, int column )
{
int mask;
int count;
count = 0;
mask = 1 << 8;
while( mask )
{
if ( mask & p[row][column] )
count++;
mask >>= 1;
}
return( count );
}
void figure_possibles( int a[9][9], int p[9][9] )
{
int row, column;
int digit;
int i;
int box_row, box_column;
int box_row_start, box_column_start;
for ( row = 0; row < 9; row++ )
for ( column = 0; column < 9; column++ )
{
p[row][column] = 0;
for ( digit = 1; digit <= 9; digit++ )
set_possible( p, row, column, digit );
}
for ( row = 0; row < 9; row++ )
for ( column = 0; column < 9; column++ )
{
digit = a[row][column];
if ( 0 == digit )
continue;
for ( i = 1; i <= 9; i++ )
set_impossible( p, row, column, i );
for ( i = 0; i < 9; i++ )
set_impossible( p, row, i, digit );
for ( i = 0; i < 9; i++ )
set_impossible( p, i, column, digit );
box_row_start = (int)( row / 3 ) * 3;
box_column_start = (int)( column / 3 ) * 3;
for ( box_row = box_row_start; box_row < box_row_start + 3; box_row++ )
for ( box_column = box_column_start; box_column < box_column_start + 3; box_column++ )
set_impossible( p, box_row, box_column, digit );
}
}
void show_matrix( int a[9][9] )
{
int row, column;
int p[9][9];
figure_possibles( a, p );
for ( row = 0; row < 9; row++ )
{
for ( column = 0; column < 9; column++ )
if ( a[row][column] )
printf( " %d", a[row][column] );
else
printf( " _" );
printf( " " );
for ( column = 0; column < 9; column++ )
printf( " %03X", p[row][column] );
printf( " " );
for ( column = 0; column < 9; column++ )
printf( " %d", count_possible( p, row, column ));
printf( "\n" );
}
printf( "\n" );
}
int set_cell( int a[9][9], int row, int column, int digit )
{
int i;
int box_row, box_column;
int box_row_start, box_column_start;
if (( row < 0 ) || ( row > 8 ))
return( E_BAD_ROW );
if (( column < 0 ) || ( column > 8 ))
return( E_BAD_COLUMN );
for ( i = 0; i < 9; i++ )
if ( digit == a[row][i] )
return( E_ALREADY_SET );
for ( i = 0; i < 9; i++ )
if ( digit == a[i][column] )
return( E_ALREADY_SET );
box_row_start = (int)( row / 3 ) * 3;
box_column_start = (int)( column / 3 ) * 3;
for ( box_row = box_row_start; box_row < box_row_start + 3; box_row++ )
for ( box_column = box_column_start; box_column < box_column_start + 3; box_column++ )
if ( digit == a[box_row][box_column] )
return( E_ALREADY_SET );
a[row][column] = digit;
return( E_OK );
}
int load_matrix( int a[9][9], int m[9][9] )
{
int row, column;
int result;
zero_matrix( a );
for ( row = 0; row < 9; row++ )
for ( column = 0; column < 9; column++ )
if ( m[row][column] )
{
result = set_cell( a, row, column, m[row][column] );
if ( E_OK != result )
{
printf( "Set Cell( %d, %d, %d ) returned error %d.\n",
row, column, m[row][column], result );
return( result );
}
}
return( E_OK );
}
int find_lowest( int p[9][9], int *low_row, int *low_column )
{
int row, column;
int count;
int lowest_possible;
lowest_possible = 10;
for ( row = 0; row < 9; row++ )
for ( column = 0; column < 9; column++ )
{
count = count_possible( p, row, column );
if (( count ) && ( count < lowest_possible ))
{
lowest_possible = count;
*low_row = row;
*low_column = column;
}
}
if ( lowest_possible > 9 )
lowest_possible = 0;
return( lowest_possible );
}
int solve_matrix( int depth, int a[9][9], int set_row, int set_column, int set_digit )
{
int row, column;
int count;
int digit;
int turn_number;
int i;
int result;
int h[9][9];
int p[9][9];
for ( row = 0; row < 9; row++ )
for ( column = 0; column < 9; column++ )
h[row][column] = a[row][column];
if ( set_digit )
{
result = set_cell( h, set_row, set_column, set_digit );
if ( E_OK != result )
return( result );
}
printf( "Call to Solve_Matrix at depth %d with request to set (%d,%d) to %d:\n",
depth, set_row, set_column, set_digit );
show_matrix( h );
figure_possibles( h, p );
for ( row = 0; row < 9; row++ )
for ( column = 0; column < 9; column++ )
if (( 0 == h[row][column] ) && ( 0 == count_possible( p, row, column )))
return( E_LACKING_POSSIBILITIES );
count = find_lowest( p, &row, &column );
if ( count < 1 )
{
for ( row = 0; row < 9; row++ )
for ( column = 0; column < 9; column++ )
w[row][column] = h[row][column];
return( E_DONE );
}
printf( "Lowest is %d possibilit%s at (%d,%d).\n",
count, ( count == 1 ) ? "y" : "ies", row, column );
for ( digit = 1; digit <= 9; digit++ )
if ( is_possible( p, row, column, digit ))
{
result = solve_matrix( depth + 1, h, row, column, digit );
if ( E_DONE == result )
break;
}
return( result );
}
int do_test( int m[9][9] )
{
int result;
int a[9][9];
load_matrix( a, m );
printf( "MATRIX LOADED:\n" );
show_matrix( a );
result = solve_matrix( 0, a, 0, 0, 0 );
if ( E_DONE == result )
printf( "SOLVED:\n" );
else
printf( "ERROR %d:\n", result );
show_matrix( w );
return( result );
}
int main( int argc, char *argv[] )
{
int result;
result = do_test( test_zero );
result = do_test( test_one );
result = do_test( test_two );
return( 0 );
}
The program produces a trace of each step, which can result in a rather lengthy output. Here's an edited example:
MATRIX LOADED: 4 _ _ _ 6 _ _ _ 9 000 012 056 087 000 087 057 052 000 0 2 4 4 0 4 5 3 0 _ _ 8 7 _ 5 4 _ _ 124 122 000 000 107 000 000 022 024 3 3 0 0 4 0 0 2 2 _ 1 _ _ _ _ _ 8 _ 164 000 176 10E 106 10E 076 000 074 4 0 6 4 3 4 5 0 4 _ 7 _ _ _ _ _ 4 _ 125 000 135 137 117 127 1B2 000 0B0 4 0 5 6 5 5 5 0 3 2 _ _ _ 8 _ _ _ 1 000 138 13C 13C 000 16C 170 170 000 0 4 5 5 0 5 4 4 0 _ 8 _ _ _ _ _ 3 _ 121 000 139 13B 153 16B 172 000 070 3 0 5 6 5 6 5 0 3 _ 3 _ _ _ _ _ 1 _ 1E0 000 16A 1B2 152 1E2 1F0 000 0F8 4 0 5 5 4 5 5 0 5 5 _ _ _ 4 _ _ _ 2 000 120 161 1A5 000 1E5 1E4 160 000 0 2 4 5 0 6 5 3 0 _ _ _ _ _ _ _ _ _ 1E1 12A 16B 1B7 157 1E7 1F4 170 0FC 5 4 6 7 6 7 6 4 6 [...] SOLVED: 4 2 7 3 6 8 1 5 9 000 000 000 000 000 000 000 000 000 0 0 0 0 0 0 0 0 0 9 6 8 7 1 5 4 2 3 000 000 000 000 000 000 000 000 000 0 0 0 0 0 0 0 0 0 3 1 5 4 2 9 6 8 7 000 000 000 000 000 000 000 000 000 0 0 0 0 0 0 0 0 0 1 7 3 6 5 2 9 4 8 000 000 000 000 000 000 000 000 000 0 0 0 0 0 0 0 0 0 2 5 4 9 8 3 7 6 1 000 000 000 000 000 000 000 000 000 0 0 0 0 0 0 0 0 0 6 8 9 1 7 4 2 3 5 000 000 000 000 000 000 000 000 000 0 0 0 0 0 0 0 0 0 7 3 2 5 9 6 8 1 4 000 000 000 000 000 000 000 000 000 0 0 0 0 0 0 0 0 0 5 9 6 8 4 1 3 7 2 000 000 000 000 000 000 000 000 000 0 0 0 0 0 0 0 0 0 8 4 1 2 3 7 5 9 6 000 000 000 000 000 000 000 000 000 0 0 0 0 0 0 0 0 0
|