Quite awhile back, I converted a "C" backtracking solver program by
gsf into an embedded backtracking solver where you pass it a character array containing the puzzle and it returns {0,1,2} for {none,one,multiple} solutions.
For comments on its speed vs DLX, see
here.
If you are interested: (Note: you can
not feed it a solved puzzle!)
- Code: Select all
/*
* Glenn Fowler
* AT&T Research
* 9x9 sudoku backtrack solver -- no dancing
*/
/* converted to an embedded solver by Danny A. Jones */
#define N1 3
#define N2 9
#define N4 81
#include <mem.h>
#define SET(A,VALUE) memset( A, VALUE, sizeof(A) )
#define ZERO(A) SET( A, 0 )
#define MASK(g,i) (g.rcb[cell_rcb[i][0]]&g.rcb[cell_rcb[i][1]]&g.rcb[cell_rcb[i][2]])
#define PROP(g,i,x) (g.rcb[cell_rcb[i][0]]^=(x),g.rcb[cell_rcb[i][1]]^=(x),g.rcb[cell_rcb[i][2]]^=(x))
#define MOVE(g,i,x) (g.cell[i]=(x),PROP(g,i,x))
#define UNDO(g,i,x) (g.cell[i]=(0),PROP(g,i,x))
typedef struct Grid_s { /* rcb -> Row/Column/Block as bitmap of values
cell -> solution value as bitmap of value */
unsigned int rcb[27], cell[N4];
} Grid_t;
static const char name[] = ".123456789"; /* self-descriptive */
static unsigned short token [256]; /* bit-map for [name []] */
static unsigned char ident [512]; /* value of [token[]] */
static unsigned short next [512]; /* LSB of [] */
static unsigned char cell_rcb[N4][N1]; /* rcb indices for cell [] */
static Grid_t base; /* initial grid w/all rcb[] active */
static const int BC_9[512] = {
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2,
2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3,
2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4,
4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4,
2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4,
4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5,
4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6,
6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3,
3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5,
4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4,
4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,
4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5,
5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7,
6, 7, 7, 8, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4,
4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4,
4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4,
3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5,
5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6,
4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6,
6, 7, 6, 7, 7, 8, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5,
4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6,
6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4,
4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6,
5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6,
6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8,
6, 7, 7, 8, 7, 8, 8, 9 };
void once_gsf( void ) { /* called once at program initialization */
int i, j, k, n;
/* ZERO( base ); */ memset( &base, 0, sizeof( base ) );
ZERO( cell_rcb );
ZERO( ident );
ZERO( next );
ZERO( token );
token['.'] = token['0'] = token['X'] = token['_'] = 0x1ff;
for (i = 1; i <= N2; i++)
{
ident[token[name[i]] = (1<<(i-1))] = i;
}
for (i = 0; i < 27; i++)
base.rcb[i] = 0x1ff;
for (i = 0; i < 512; i++) {
k = 0;
for (j = 1; j < 512; j <<= 1)
if ((i & j) && !k++)
next[i] = j;
}
for (k = i = 0; i < N2; i++) {
n = 18 + ((i / N1) * N1);
for (j = N2; j < 18; j++) {
cell_rcb[k][0] = i;
cell_rcb[k][1] = j;
cell_rcb[k][2] = n + ((j / N1) % N1);
k++;
}
}
}
typedef struct Try_s { /* list of unresolved cells */
int candidates, cell, free, guess, index;
} Try_t;
int gsf( char * c_puzzle ) {
int i, j, k, m, n, x;
int depth, level, solutions;
Grid_t grid;
Try_t try[N4];
ZERO( try );
grid = base;
depth = level = solutions = 0;
for ( i = 0 ; i < N4 ; i++ )
if ((j = token[c_puzzle[i]]) == 0x1ff)
try[depth++].free = i;
else
MOVE(grid, i, j);
for (;;) {
m = 10;
for (k = level; k < depth; k++) {
i = try[k].free;
if (!(x = grid.cell[i] = MASK(grid, i))) {
m = 11;
break;
}
if (m > (n = BC_9[x])) {
try[level+1].index = k;
try[level+1].candidates = x;
if ((m = n) == 1)
break;
}
}
if (m < 10) {
k = try[level+1].index;
try[level+1].cell = try[k].free;
if (k != level) {
j = try[level].free;
try[level].free = try[k ].free;
try[k ].free = j;
}
level++;
}
else {
if (m == 10) {
if (solutions++) {
break;
}
}
UNDO(grid, try[level].cell, try[level].guess);
}
while (!(x = next[try[level].candidates])) {
if (!--level) {
return ( solutions );
}
UNDO(grid, try[level].cell, try[level].guess);
}
try[level].candidates ^= x;
try[level].guess = x;
MOVE(grid, try[level].cell, x);
}
return ( solutions ); /* {0,1,2} == {no,one,multiple} */
}
/*
__________________________________________________________________________________________________________
*/