On Oct 16, 7:08*am, Boon <root@localhost> wrote:
> Hello group,
>
> I've been toying with a simple sudoku[1] solver. I meant for the code to
> be short and easy to understand. I figured "brute force is simple" --
> who needs finesse, when you've got muscle, right? 
>
> [1]http://en.wikipedia.org/wiki/Sudoku
>
> Thus, the strategy is to test every legal "move" and to backtrack when
> stuck. A recursive function seemed appropriate. I'd like to hear
> comments and suggestions regarding the implementation.
>
> Regards.
>
> #include <stdio.h>
>
> static int grid[9][9];
>
> void read_grid(FILE *fp)
> {
> * *int i,j;
> * *for (i=0; i < 9; ++i)
> * *{
> * * *char buf[16];
> * * *fgets(buf, sizeof buf, fp);
> * * *for (j=0; j < 9; ++j)
> * * *{
> * * * *char c = buf[j];
> * * * *if ('1' <= c && c <= '9') grid[i][j] = c - '0';
> * * *}
> * *}
>
> }
>
> void write_grid(void)
> {
> * *int i, j;
> * *for (i=0; i < 9; ++i)
> * *{
> * * *for (j=0; j < 9; ++j) printf("%d ", grid[i][j]);
> * * *putchar('\n');
> * *}
>
> }
>
> int is_legal(int row, int col, int val)
> {
> * *int ii = row - row%3;
> * *int jj = col - col%3;
> * *int i, j, k = 0, res = 1;
> * *for (i=0; i < 3; ++i)
> * * *for (j=0; j < 3; ++j, ++k)
> * * * *res = res && (grid[row][k] != val) && (grid[k][col] != val) &&
> (grid[ii+i][jj+j] != val);
> * *return res;
>
> }
>
> void solve(int pos)
> {
> * *if (pos == 9*9) write_grid();
> * *else
> * *{
> * * *int row, col, val;
> * * *row = pos / 9;
> * * *col = pos % 9;
> * * *if (grid[row][col] != 0) solve(pos+1);
> * * *else
> * * *{
> * * * *for (val=1; val <= 9; ++val)
> * * * *{
> * * * * *if (is_legal(row, col, val))
> * * * * *{
> * * * * * *grid[row][col] = val;
> * * * * * *solve(pos+1);
> * * * * *}
> * * * *}
> * * * *grid[row][col] = 0;
> * * *}
> * *}
>
> }
>
> int main(void)
> {
> * *read_grid(stdin);
> * *solve(0);
> * *return 0;
>
>
>
> }
Compare your method with this:
/* Program resolution of sudoku grids by backtracking,
with propagation of the constraints and variable
selection the most constrained (mrv: minimum remaining value).
The file is read from stdin. Try for example with:
53..7....
6..195...
.98....6.
8...6...3
4..8.3..1
7...2...6
.6....28.
...419..5
....8..79
Bernard Helmstetter, 2006
Translated to English by Dann Corbit
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define UNKNOWN 0
int grid[81];
int domain[81][10]; /* The list of possibilities */
int domain_cuts[81]; /* domain cuts */
int computer_nodes;
/* Read the grid from standard input, using the characters '0'-'9' and
'.' */
void read_grid()
{
int k = 0;
while (k < 81) {
char c = getchar();
if (c >= '1' && c <= '9')
grid[k++] = c - '0';
else if (c == '.')
grid[k++] = UNKNOWN;
else if (c == EOF) {
fprintf(stderr, "Bad format reading grid\n");
exit(1);
}
}
}
/* print the grid to standard output */
void print_grid()
{
int c,
l;
for (l = 0; l < 9; l++) {
for (c = 0; c < 9; c++) {
int k = l * 9 + c;
if (grid[k] == UNKNOWN)
printf(".");
else
printf("%c", grid[k] + '0');
}
putchar('\n');
}
putchar('\n');
}
/* remove all the values of the domains that are incompatible for case
'i' */
void restrict_domain(int i)
{
int l = i / 9,
c = i % 9;
int lb = l / 3;
int cb = c / 3;
int l2,
c2,
lr2,
cr2,
i2;
/* column constraints for case 'i' */
for (l2 = 0; l2 < 9; l2++) {
i2 = l2 * 9 + c;
if (domain[i2][grid[i]]) {
domain[i2][grid[i]] = 0;
domain_cuts[i2]--;
}
}
/* row constraints for case 'i' */
for (c2 = 0; c2 < 9; c2++) {
i2 = l * 9 + c2;
if (domain[i2][grid[i]]) {
domain[i2][grid[i]] = 0;
domain_cuts[i2]--;
}
}
/* verify the region containing case 'i' */
for (lr2 = 0; lr2 < 3; lr2++)
for (cr2 = 0; cr2 < 3; cr2++) {
i2 = (lb * 3 + lr2) * 9 + (cb * 3 + cr2);
if (domain[i2][grid[i]]) {
domain[i2][grid[i]] = 0;
domain_cuts[i2]--;
}
}
}
/* using the initial state, initialize the domain table */
void init_domain()
{
int i,
v;
for (i = 0; i < 81; i++) {
domain_cuts[i] = 9;
for (v = 1; v <= 9; v++)
domain[i][v] = 1;
}
/* restrict the domain by backtracking */
for (i = 0; i < 81; i++)
if (grid[i] != UNKNOWN)
restrict_domain(i);
}
void backtrack()
{
int i,
i_min = -1;
int cuts_min = 10;
int domain2[81][10];
int domain_cuts2[81];
/* look for a smaller domain */
for (i = 0; i < 81; i++) {
if (grid[i] == UNKNOWN && domain_cuts[i] < cuts_min) {
i_min = i;
cuts_min = domain_cuts[i];
}
}
/* Are all UNKNOWN fields resolved? */
if (i_min == -1) {
print_grid(); /* solution found */
return;
}
computer_nodes++;
for (grid[i_min] = 1; grid[i_min] <= 9; grid[i_min]++) {
if (domain[i_min][grid[i_min]] == 0)
continue;
/* Save the state between recursive calls */
memcpy(domain2, domain, sizeof(domain));
memcpy(domain_cuts2, domain_cuts, sizeof(domain_cuts));
restrict_domain(i_min);
backtrack();
memcpy(domain, domain2, sizeof(domain));
memcpy(domain_cuts, domain_cuts2, sizeof(domain_cuts));
}
grid[i_min] = UNKNOWN;
}
int main()
{
read_grid();
print_grid();
init_domain();
backtrack(0);
printf("%d nodes searched\n", computer_nodes);
return 0;
}