diff --git a/meson.build b/meson.build index 64e121f..174b9ec 100644 --- a/meson.build +++ b/meson.build @@ -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', diff --git a/src/solver/internals.h b/src/solver/internals.h index eca7af0..3ddaa72 100644 --- a/src/solver/internals.h +++ b/src/solver/internals.h @@ -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 */ diff --git a/src/solver/slice_and_dice.c b/src/solver/slice_and_dice.c new file mode 100644 index 0000000..aba5a64 --- /dev/null +++ b/src/solver/slice_and_dice.c @@ -0,0 +1,82 @@ +#include "internals.h" + +#include + +#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; +} diff --git a/src/solver/solve.c b/src/solver/solve.c index d6d6932..bc1b4f8 100644 --- a/src/solver/solve.c +++ b/src/solver/solve.c @@ -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);