Skip to content

Commit 64f1294

Browse files
committed
sudoku: distinguish between correct and valid solutions.
1 parent 5d911b1 commit 64f1294

File tree

1 file changed

+50
-36
lines changed

1 file changed

+50
-36
lines changed

sudoku/sudoku.c

Lines changed: 50 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,16 @@ static_assert(sizeof(Cell) * 8 >= BOARD_SIZE, "Cell width not big enough!");
1818
static const Cell UNKNOWN = (1 << BOARD_SIZE) - 1;
1919

2020
bool stop(Cell board[/*BOARD_SIZE*/][BOARD_SIZE]);
21-
bool isValid(Cell board[/*BOARD_SIZE*/][BOARD_SIZE]);
21+
bool isComplete(Cell board[/*BOARD_SIZE*/][BOARD_SIZE]);
2222

2323
void column(Cell board[/*BOARD_SIZE*/][BOARD_SIZE], size_t c, Cell* set[/*BOARD_SIZE*/]);
2424
void row(Cell board[/*BOARD_SIZE*/][BOARD_SIZE], size_t r, Cell* set[/*BOARD_SIZE*/]);
2525
void block(Cell board[/*BOARD_SIZE*/][BOARD_SIZE], size_t b, Cell* set[/*BOARD_SIZE*/]);
2626

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

30-
int bitNum(Cell c) { for (int i = 0; ; ++i) if ((1 << (i - 1)) >= c) return i; }
30+
int bitNum(Cell c) { for (int i = 0; ; ++i) if (1 << (i - 1) >= c) return i; }
3131
void printBoard(Cell board[/*BOARD_SIZE*/][BOARD_SIZE], bool pretty)
3232
{
3333
for (size_t i = 0; i < BOARD_SIZE; ++i) {
@@ -84,37 +84,41 @@ int main(int argc, char* argv[])
8484
}
8585
}
8686

87-
typedef void (*SetGetter)(Cell /*board*/[][BOARD_SIZE], size_t /*idx*/, Cell* /*res*/[]);
88-
SetGetter set_getters[] = {column, row, block, NULL};
87+
typedef void (*GroupGetter)(Cell /*board*/[][BOARD_SIZE], size_t /*idx*/, Cell* /*res*/[]);
88+
GroupGetter groupers[] = {column, row, block, NULL};
8989

9090
int num_iters = 0;
91+
bool valid = false;
9192
while (!stop(board)) {
93+
++num_iters;
9294
Cell* cells[BOARD_SIZE];
93-
for (SetGetter* getSet = &set_getters[0]; *getSet != NULL; ++getSet) {
94-
for (size_t set_i = 0; set_i < BOARD_SIZE; ++set_i) {
95-
(*getSet)(board, set_i, cells);
95+
for (GroupGetter* groupCells = &groupers[0]; *groupCells != NULL; ++groupCells) {
96+
for (size_t group_i = 0; group_i < BOARD_SIZE; ++group_i) {
97+
(*groupCells)(board, group_i, cells);
9698

9799
if (PRINT_DEBUG) {
98100
printBoard(board, false);
99101
printf("Cells: %s %zd\n",
100-
*getSet == column ? "Col" : *getSet == row ? "Row" : "Block", set_i + 1);
102+
*groupCells == column ? "Col" : *groupCells == row ? "Row" : "Block", group_i + 1);
101103
}
102-
solveByCells(cells);
104+
if (!solveByCells(cells)) goto invalid_soln_l;
103105

104106
if (PRINT_DEBUG) {
105107
printBoard(board, false);
106108
printf("Possibilites: %s %zd\n",
107-
*getSet == column ? "Col" : *getSet == row ? "Row" : "Block", set_i + 1);
109+
*groupCells == column ? "Col" : *groupCells == row ? "Row" : "Block", group_i + 1);
108110
}
109-
solveByPossibilities(cells);
111+
if (!solveByPossibilities(cells)) goto invalid_soln_l;
110112
}
111113
}
112-
++num_iters;
113114
}
115+
valid = true;
116+
invalid_soln_l:;
114117

115-
const bool valid = isValid(board);
116-
printf("%s result found! Took %i iterations.\n", valid ? "Valid" : "Invalid", num_iters);
117-
printBoard(board, valid);
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);
118122
}
119123

120124
void column(Cell board[/*BOARD_SIZE*/][BOARD_SIZE], size_t c, Cell* set[/*BOARD_SIZE*/])
@@ -133,15 +137,15 @@ void block(Cell board[/*BOARD_SIZE*/][BOARD_SIZE], size_t b, Cell* set[/*BOARD_S
133137
for (size_t i = 0; i < BOARD_SIZE; ++i) set[i] = &board[b / s * s + i / s][b % s * s + i % s];
134138
}
135139

136-
int countBits(uint16_t val);
140+
int countBits(Cell val);
137141

138142
bool stop(Cell board[/*BOARD_SIZE*/][BOARD_SIZE])
139143
{
140144
static Cell prev_board[BOARD_SIZE][BOARD_SIZE] = { { 0 } };
141145
bool res = true;
142146
for (size_t i = 0; i < BOARD_SIZE; ++i) {
143147
for (size_t j = 0; j < BOARD_SIZE; ++j) {
144-
if (prev_board[i][j] != board[i][j] && countBits(board[i][j]) != 1) {
148+
if (prev_board[i][j] != board[i][j]) {
145149
res = false;
146150
prev_board[i][j] = board[i][j];
147151
}
@@ -150,7 +154,7 @@ bool stop(Cell board[/*BOARD_SIZE*/][BOARD_SIZE])
150154
return res;
151155
}
152156

153-
bool isValid(Cell board[/*BOARD_SIZE*/][BOARD_SIZE])
157+
bool isComplete(Cell board[/*BOARD_SIZE*/][BOARD_SIZE])
154158
{
155159
for (size_t i = 0; i < BOARD_SIZE; ++i) {
156160
for (size_t j = 0; j < BOARD_SIZE; ++j) {
@@ -162,70 +166,80 @@ bool isValid(Cell board[/*BOARD_SIZE*/][BOARD_SIZE])
162166
return true;
163167
}
164168

165-
void solveByCells(Cell* cells[/*BOARD_SIZE*/])
169+
bool solveByCells(Cell* cells[/*BOARD_SIZE*/])
166170
{
167171
for (size_t i = 0; i < BOARD_SIZE; ++i) {
168-
bool subsets[BOARD_SIZE] = { false };
172+
Cell mask = 0;
169173
int num_subsets = 0;
170174

171-
const uint16_t vals = *cells[i];
175+
const Cell vals = *cells[i];
172176
for (size_t j = i; j < BOARD_SIZE; ++j) {
173177
if ((*cells[j] | vals) == vals) {
174-
subsets[j] = true;
178+
mask |= 1 << j;
175179
++num_subsets;
176180
}
177181
}
178182

179-
if (countBits(vals) == num_subsets) {
183+
const int num_vals = countBits(vals);
184+
if (num_vals == num_subsets) {
180185
bool changed = false;
181186
for (size_t j = 0; j < BOARD_SIZE; ++j) {
182187
const Cell old = *cells[j];
183-
*cells[j] &= subsets[j] ? vals : ~vals & UNKNOWN;
188+
*cells[j] &= ((1 << j) & mask) ? vals : ~vals & UNKNOWN;
184189
if (*cells[j] != old) changed = true;
185190
}
186-
if (PRINT_DEBUG && changed) printf("Set of %i cells fulfilling %i.\n", num_subsets, vals);
191+
if (PRINT_DEBUG && changed) printf("Set %i of cells fulfilling %i.\n", mask, vals);
192+
} else if (num_vals < num_subsets) {
193+
if (PRINT_DEBUG) printf("Set %i of cells overfulfill %i!\n", mask, vals);
194+
return false;
187195
}
188196
}
197+
return true;
189198
}
190199

191-
uint16_t transposeBits(Cell* const cells[], size_t bit_i);
200+
Cell transposeBits(Cell* const cells[/*BOARD_SIZE*/], size_t bit_i);
192201

193-
void solveByPossibilities(Cell* cells[/*BOARD_SIZE*/])
202+
bool solveByPossibilities(Cell* cells[/*BOARD_SIZE*/])
194203
{
195204
for (size_t i = 0; i < BOARD_SIZE; ++i) {
196-
uint16_t mask = 0;
205+
Cell mask = 0;
197206
int num_subsets = 0;
198207

199-
const uint16_t vals = transposeBits(cells, i);
208+
const Cell vals = transposeBits(cells, i);
200209
for (size_t j = i; j < BOARD_SIZE; ++j) {
201210
if ((transposeBits(cells, j) | vals) == vals) {
202211
mask |= 1 << j;
203212
++num_subsets;
204213
}
205214
}
206215

207-
if (countBits(vals) == num_subsets) {
216+
const int num_vals = countBits(vals);
217+
if (num_vals == num_subsets) {
208218
bool changed = false;
209219
for (size_t j = 0; j < BOARD_SIZE; ++j) {
210220
const Cell old = *cells[j];
211221
*cells[j] &= ((1 << j) & vals) ? mask : ~mask & UNKNOWN;
212222
if (*cells[j] != old) changed = true;
213223
}
214-
if (PRINT_DEBUG && changed) printf("Set of %i possibilities fulfilled by %i.\n", num_subsets, mask);
224+
if (PRINT_DEBUG && changed) printf("Set %i of possibilities fulfilled by %i.\n", vals, mask);
225+
} else if (num_vals < num_subsets) {
226+
if (PRINT_DEBUG) printf("Set %i of possibilities cannot be fulfilled by %i!\n", vals, mask);
227+
return false;
215228
}
216229
}
230+
return true;
217231
}
218232

219-
int countBits(uint16_t val)
233+
int countBits(Cell val)
220234
{
221235
int res = 0;
222236
for (size_t i = 0; i < BOARD_SIZE; ++i) if (val & (1 << i)) ++res;
223237
return res;
224238
}
225239

226-
uint16_t transposeBits(Cell* const cells[], size_t bit_i)
240+
Cell transposeBits(Cell* const cells[/*BOARD_SIZE*/], size_t bit_i)
227241
{
228-
uint16_t res = 0;
242+
Cell res = 0;
229243
for (size_t i = 0; i < BOARD_SIZE; ++i) if (*cells[i] & (1 << bit_i)) res |= 1 << i;
230244
return res;
231245
}

0 commit comments

Comments
 (0)