Skip to content

Commit 636b6cf

Browse files
committed
sudoku: add guess-n-check
1 parent 64f1294 commit 636b6cf

File tree

1 file changed

+74
-40
lines changed

1 file changed

+74
-40
lines changed

sudoku/sudoku.c

Lines changed: 74 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,22 @@
1313
#define BOARD_SIZE ((size_t) (SQUARE_SIDE * SQUARE_SIDE))
1414

1515
typedef uint16_t Cell;
16-
static_assert(sizeof(Cell) * 8 >= BOARD_SIZE, "Cell width not big enough!");
16+
static_assert(sizeof(Cell) * 8 > BOARD_SIZE, "Cell width not big enough!");
1717

1818
static const Cell UNKNOWN = (1 << BOARD_SIZE) - 1;
1919

20-
bool stop(Cell board[/*BOARD_SIZE*/][BOARD_SIZE]);
21-
bool isComplete(Cell board[/*BOARD_SIZE*/][BOARD_SIZE]);
20+
void copyBoard(const Cell src[/*BOARD_SIZE*/][BOARD_SIZE], Cell dest[/*BOARD_SIZE*/][BOARD_SIZE]);
21+
bool changed(const Cell src[/*BOARD_SIZE*/][BOARD_SIZE], Cell dest[/*BOARD_SIZE*/][BOARD_SIZE]);
22+
bool isComplete(const Cell board[/*BOARD_SIZE*/][BOARD_SIZE]);
2223

2324
void column(Cell board[/*BOARD_SIZE*/][BOARD_SIZE], size_t c, Cell* set[/*BOARD_SIZE*/]);
2425
void row(Cell board[/*BOARD_SIZE*/][BOARD_SIZE], size_t r, Cell* set[/*BOARD_SIZE*/]);
2526
void block(Cell board[/*BOARD_SIZE*/][BOARD_SIZE], size_t b, Cell* set[/*BOARD_SIZE*/]);
2627

27-
bool solveByCells(Cell* cells[/*BOARD_SIZE*/]);
28-
bool solveByPossibilities(Cell* cells[/*BOARD_SIZE*/]);
28+
bool solveNaked(Cell board[/*BOARD_SIZE*/][BOARD_SIZE]);
2929

3030
int bitNum(Cell c) { for (int i = 0; ; ++i) if (1 << (i - 1) >= c) return i; }
31-
void printBoard(Cell board[/*BOARD_SIZE*/][BOARD_SIZE], bool pretty)
31+
void printBoard(const Cell board[/*BOARD_SIZE*/][BOARD_SIZE], bool pretty)
3232
{
3333
for (size_t i = 0; i < BOARD_SIZE; ++i) {
3434
if (i > 0 && i % SQUARE_SIDE == 0) {
@@ -49,6 +49,8 @@ void printBoard(Cell board[/*BOARD_SIZE*/][BOARD_SIZE], bool pretty)
4949

5050
static bool PRINT_DEBUG = false;
5151

52+
static int num_iters = 0;
53+
5254
int main(int argc, char* argv[])
5355
{
5456
const char* board_str;
@@ -84,12 +86,46 @@ int main(int argc, char* argv[])
8486
}
8587
}
8688

89+
bool valid, complete;
90+
Cell prev_board[BOARD_SIZE][BOARD_SIZE] = { { 0 } };
91+
while ((valid = solveNaked(board)) && !(complete = isComplete(board)) && changed(board, prev_board)) {
92+
for (size_t i = 0; i < BOARD_SIZE; ++i) {
93+
for (size_t j = 0; j < BOARD_SIZE; ++j) {
94+
Cell accum[BOARD_SIZE][BOARD_SIZE] = { { 0 } };
95+
for (Cell c = 1; c < UNKNOWN; c <<= 1) {
96+
Cell guess[BOARD_SIZE][BOARD_SIZE];
97+
copyBoard(board, guess);
98+
guess[i][j] &= c;
99+
if (guess[i][j] == 0) continue;
100+
if (solveNaked(guess)) {
101+
for (size_t i = 0; i < BOARD_SIZE; ++i) {
102+
for (size_t j = 0; j < BOARD_SIZE; ++j) {
103+
accum[i][j] |= guess[i][j];
104+
}
105+
}
106+
}
107+
}
108+
if (changed(accum, board)) goto break_outer_l;
109+
}
110+
}
111+
break_outer_l:;
112+
}
113+
114+
printf("%s, %s result found! Took %i iterations.\n",
115+
valid ? "Valid" : "Invalid", complete ? "Complete" : "Incomplete", num_iters);
116+
printBoard(board, complete);
117+
}
118+
119+
bool solveByCells(Cell* cells[/*BOARD_SIZE*/]);
120+
bool solveByPossibilities(Cell* cells[/*BOARD_SIZE*/]);
121+
122+
bool solveNaked(Cell board[/*BOARD_SIZE*/][BOARD_SIZE])
123+
{
87124
typedef void (*GroupGetter)(Cell /*board*/[][BOARD_SIZE], size_t /*idx*/, Cell* /*res*/[]);
88125
GroupGetter groupers[] = {column, row, block, NULL};
89126

90-
int num_iters = 0;
91-
bool valid = false;
92-
while (!stop(board)) {
127+
Cell prev_board[BOARD_SIZE][BOARD_SIZE] = { { 0 } };
128+
while (changed(board, prev_board)) {
93129
++num_iters;
94130
Cell* cells[BOARD_SIZE];
95131
for (GroupGetter* groupCells = &groupers[0]; *groupCells != NULL; ++groupCells) {
@@ -101,60 +137,42 @@ int main(int argc, char* argv[])
101137
printf("Cells: %s %zd\n",
102138
*groupCells == column ? "Col" : *groupCells == row ? "Row" : "Block", group_i + 1);
103139
}
104-
if (!solveByCells(cells)) goto invalid_soln_l;
140+
if (!solveByCells(cells)) return false;
105141

106142
if (PRINT_DEBUG) {
107143
printBoard(board, false);
108144
printf("Possibilites: %s %zd\n",
109145
*groupCells == column ? "Col" : *groupCells == row ? "Row" : "Block", group_i + 1);
110146
}
111-
if (!solveByPossibilities(cells)) goto invalid_soln_l;
147+
if (!solveByPossibilities(cells)) return false;
112148
}
113149
}
114150
}
115-
valid = true;
116-
invalid_soln_l:;
117-
118-
const bool complete = isComplete(board);
119-
printf("%s, %s result found! Took %i iterations.\n",
120-
complete ? "Complete" : "Incomplete", valid ? "valid" : "invalid", num_iters);
121-
printBoard(board, complete);
122-
}
123-
124-
void column(Cell board[/*BOARD_SIZE*/][BOARD_SIZE], size_t c, Cell* set[/*BOARD_SIZE*/])
125-
{
126-
for (size_t i = 0; i < BOARD_SIZE; ++i) set[i] = &board[i][c];
127-
}
128-
129-
void row(Cell board[/*BOARD_SIZE*/][BOARD_SIZE], size_t r, Cell* set[/*BOARD_SIZE*/])
130-
{
131-
for (size_t i = 0; i < BOARD_SIZE; ++i) set[i] = &board[r][i];
151+
return true;
132152
}
133153

134-
void block(Cell board[/*BOARD_SIZE*/][BOARD_SIZE], size_t b, Cell* set[/*BOARD_SIZE*/])
154+
void copyBoard(const Cell src[/*BOARD_SIZE*/][BOARD_SIZE], Cell dest[/*BOARD_SIZE*/][BOARD_SIZE])
135155
{
136-
const size_t s = SQUARE_SIDE;
137-
for (size_t i = 0; i < BOARD_SIZE; ++i) set[i] = &board[b / s * s + i / s][b % s * s + i % s];
156+
changed(src, dest);
138157
}
139158

140-
int countBits(Cell val);
141-
142-
bool stop(Cell board[/*BOARD_SIZE*/][BOARD_SIZE])
159+
bool changed(const Cell src[/*BOARD_SIZE*/][BOARD_SIZE], Cell dest[/*BOARD_SIZE*/][BOARD_SIZE])
143160
{
144-
static Cell prev_board[BOARD_SIZE][BOARD_SIZE] = { { 0 } };
145-
bool res = true;
161+
bool res = false;
146162
for (size_t i = 0; i < BOARD_SIZE; ++i) {
147163
for (size_t j = 0; j < BOARD_SIZE; ++j) {
148-
if (prev_board[i][j] != board[i][j]) {
149-
res = false;
150-
prev_board[i][j] = board[i][j];
164+
if (src[i][j] != dest[i][j]) {
165+
res = true;
166+
dest[i][j] = src[i][j];
151167
}
152168
}
153169
}
154170
return res;
155171
}
156172

157-
bool isComplete(Cell board[/*BOARD_SIZE*/][BOARD_SIZE])
173+
int countBits(Cell val);
174+
175+
bool isComplete(const Cell board[/*BOARD_SIZE*/][BOARD_SIZE])
158176
{
159177
for (size_t i = 0; i < BOARD_SIZE; ++i) {
160178
for (size_t j = 0; j < BOARD_SIZE; ++j) {
@@ -166,6 +184,22 @@ bool isComplete(Cell board[/*BOARD_SIZE*/][BOARD_SIZE])
166184
return true;
167185
}
168186

187+
void column(Cell board[/*BOARD_SIZE*/][BOARD_SIZE], size_t c, Cell* set[/*BOARD_SIZE*/])
188+
{
189+
for (size_t i = 0; i < BOARD_SIZE; ++i) set[i] = &board[i][c];
190+
}
191+
192+
void row(Cell board[/*BOARD_SIZE*/][BOARD_SIZE], size_t r, Cell* set[/*BOARD_SIZE*/])
193+
{
194+
for (size_t i = 0; i < BOARD_SIZE; ++i) set[i] = &board[r][i];
195+
}
196+
197+
void block(Cell board[/*BOARD_SIZE*/][BOARD_SIZE], size_t b, Cell* set[/*BOARD_SIZE*/])
198+
{
199+
const size_t s = SQUARE_SIDE;
200+
for (size_t i = 0; i < BOARD_SIZE; ++i) set[i] = &board[b / s * s + i / s][b % s * s + i % s];
201+
}
202+
169203
bool solveByCells(Cell* cells[/*BOARD_SIZE*/])
170204
{
171205
for (size_t i = 0; i < BOARD_SIZE; ++i) {

0 commit comments

Comments
 (0)