sudoku: solver: add slice and dice heuristic
This commit is contained in:
parent
b17cb8d84c
commit
e89f6bdf51
|
@ -13,6 +13,7 @@ sources = [
|
|||
'src/main.c',
|
||||
'src/solver/last_remaining.c',
|
||||
'src/solver/single_occurence.c',
|
||||
'src/solver/slice_and_dice.c',
|
||||
'src/solver/solve.c',
|
||||
'src/solver/update_sets.c',
|
||||
'src/sudoku.c',
|
||||
|
|
|
@ -8,5 +8,6 @@ struct sudoku;
|
|||
bool update_sets(const struct sudoku *grid, bool possibilities[9][9][9]);
|
||||
bool single_occurrence(struct sudoku *grid, bool possibilities[9][9][9]);
|
||||
bool last_remaining(struct sudoku *grid);
|
||||
bool slice_and_dice(bool possibilities[9][9][9]);
|
||||
|
||||
#endif /* !INTERNALS_H */
|
||||
|
|
82
src/solver/slice_and_dice.c
Normal file
82
src/solver/slice_and_dice.c
Normal file
|
@ -0,0 +1,82 @@
|
|||
#include "internals.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "sudoku.h"
|
||||
|
||||
static bool slice_line(bool possibilities[9][9][9], size_t x, size_t y) {
|
||||
bool changed = false;
|
||||
|
||||
for (int n = 0; n < 9; ++n) {
|
||||
size_t line = -1;
|
||||
bool unique = true;
|
||||
|
||||
for (size_t i = 3 * x; i < 3 * (x + 1); ++i) {
|
||||
for (size_t j = 3 * y; j < 3 * (y + 1); ++j) {
|
||||
if (!possibilities[i][j][n])
|
||||
continue;
|
||||
if (line >= 9)
|
||||
line = i;
|
||||
else if (line != i)
|
||||
unique = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (line >= 9 || !unique)
|
||||
continue;
|
||||
|
||||
for (size_t c = 0; c < 9; ++c) {
|
||||
if ((c / 3) == y)
|
||||
continue;
|
||||
changed |= possibilities[line][c][n];
|
||||
possibilities[line][c][n] = false;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static bool slice_column(bool possibilities[9][9][9], size_t x, size_t y) {
|
||||
bool changed = false;
|
||||
|
||||
for (int n = 0; n < 9; ++n) {
|
||||
size_t column = -1;
|
||||
bool unique = true;
|
||||
|
||||
for (size_t i = 3 * x; i < 3 * (x + 1); ++i) {
|
||||
for (size_t j = 3 * y; j < 3 * (y + 1); ++j) {
|
||||
if (!possibilities[i][j][n])
|
||||
continue;
|
||||
if (column >= 9)
|
||||
column = j;
|
||||
else if (column != j)
|
||||
unique = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (column >= 9 || !unique)
|
||||
continue;
|
||||
|
||||
for (size_t l = 0; l < 9; ++l) {
|
||||
if ((l / 3) == x)
|
||||
continue;
|
||||
changed |= possibilities[l][column][n];
|
||||
possibilities[l][column][n] = false;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool slice_and_dice(bool possibilities[9][9][9]) {
|
||||
bool changed = false;
|
||||
|
||||
for (size_t x = 0; x < 3; ++x) {
|
||||
for (size_t y = 0; y < 3; ++y) {
|
||||
changed |= slice_line(possibilities, x, y);
|
||||
changed |= slice_column(possibilities, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
|
@ -30,6 +30,7 @@ bool solve(struct sudoku *grid) {
|
|||
changed |= update_sets(grid, possibilities);
|
||||
changed |= single_occurrence(grid, possibilities);
|
||||
changed |= last_remaining(grid);
|
||||
changed |= slice_and_dice(possibilities);
|
||||
} while (changed);
|
||||
|
||||
return solved(grid);
|
||||
|
|
Loading…
Reference in a new issue