Restructure solver to go cell-by-cell

This commit is contained in:
Camden Dixie O'Brien 2022-11-26 02:13:33 +00:00
parent 38ce9d0abb
commit d9c416ffe0

144
solve.c
View File

@ -20,106 +20,98 @@
#include <stdio.h> #include <stdio.h>
static void setpval(struct sudoku *sud, unsigned r, unsigned c, uint16_t pval)
{
for (unsigned val = 0; val < NDIGITS; ++val) {
if (pval & 1) {
update(sud, r, c, val);
return;
}
pval >>= 1;
}
}
int solve(struct sudoku *sud) int solve(struct sudoku *sud)
{ {
unsigned r, c, n, i, j, val, np, pr, pc; unsigned r, c, n, i, j, val, sr, sc;
bool match; bool match;
uint16_t valmask, pvals; uint16_t valmask, pvals;
for (n = 0;; ++n) { for (n = 0;; ++n) {
match = false; match = false;
/* Check if only one place a value can go on each row. */
for (r = 0; r < NDIGITS; ++r) {
for (val = 0; val < NDIGITS; ++val) {
valmask = 1 << val;
np = 0;
for (c = 0; c < NDIGITS; ++c) {
if (!(sud->cells[r][c] & DETMASK)
&& sud->cells[r][c] & valmask) {
pr = r;
pc = c;
++np;
if (np > 1)
break;
}
}
if (np == 1) {
if (update(sud, pr, pc, val) != OK)
return -1;
match = true;
}
}
}
/* Check if only one place a value can go on each column. */
for (c = 0; c < NDIGITS; ++c) {
for (val = 0; val < NDIGITS; ++val) {
valmask = 1 << val;
np = 0;
for (r = 0; r < NDIGITS; ++r) {
if (!(sud->cells[r][c] & DETMASK)
&& sud->cells[r][c] & valmask) {
pr = r;
pc = c;
++np;
if (np > 1)
break;
}
}
if (np == 1) {
if (update(sud, pr, pc, val) != OK)
return -1;
match = true;
}
}
}
/* Check if only one place a value can go in each segment. */
for (i = 0; i < NDIGITS; ++i) {
for (val = 0; val < NDIGITS; ++val) {
valmask = 1 << val;
np = 0;
for (j = 0; j < NDIGITS; ++j) {
r = SEGLEN * (i / SEGLEN) + j / SEGLEN;
c = SEGLEN * (i % SEGLEN) + j % SEGLEN;
if (!(sud->cells[r][c] & DETMASK)
&& sud->cells[r][c] & valmask) {
pr = r;
pc = c;
++np;
if (np > 1)
break;
}
}
if (np == 1) {
if (update(sud, pr, pc, val) != OK)
return -1;
match = true;
}
}
}
/* Check each cell for if it has only one possible value. */
for (r = 0; r < NDIGITS; ++r) { for (r = 0; r < NDIGITS; ++r) {
for (c = 0; c < NDIGITS; ++c) { for (c = 0; c < NDIGITS; ++c) {
if (DET(sud->cells[r][c])) if (DET(sud->cells[r][c]))
continue; continue;
/*
* Check if there's only one possible value this cell
* can have.
*/
pvals = sud->cells[r][c] & PVALSMASK; pvals = sud->cells[r][c] & PVALSMASK;
for (val = 0; val < NDIGITS; ++val) { for (val = 0; val < NDIGITS; ++val) {
if (pvals & 1) { if (pvals & 1) {
if (pvals == 1) { if (pvals == 1) {
update(sud, r, c, val); update(sud, r, c, val);
match = true; match = true;
goto next_cell;
} }
break; break;
} }
pvals >>= 1; pvals >>= 1;
} }
/*
* Check if there's a possible value unique to this
* cell in its row.
*/
valmask = 0;
for (i = 0; i < NDIGITS; ++i) {
if (i != r && !DET(sud->cells[i][c]))
valmask |= sud->cells[i][c];
}
if ((pvals = sud->cells[r][c] & ~valmask)) {
setpval(sud, r, c, pvals);
match = true;
continue;
}
/*
* Check if there's a possible value unique to this
* cell in its column.
*/
valmask = 0;
for (i = 0; i < NDIGITS; ++i) {
if (i != c && !DET(sud->cells[r][i]))
valmask |= sud->cells[r][i];
}
if ((pvals = sud->cells[r][c] & ~valmask)) {
setpval(sud, r, c, pvals);
match = true;
continue;
}
/*
* Check if there's a possible value unique to this
* cell in its segment.
*/
sr = SEGLEN * (r / SEGLEN);
sc = SEGLEN * (c / SEGLEN);
valmask = 0;
for (i = sr; i < sr + SEGLEN; ++i) {
for (j = sc; j < sc + SEGLEN; ++j) {
if ((i != r || j != c) && !DET(sud->cells[i][j]))
valmask |= sud->cells[i][j];
}
}
if ((pvals = sud->cells[r][c] & ~valmask)) {
setpval(sud, r, c, pvals);
match = true;
continue;
}
next_cell:;
} }
} }