diff --git a/meson.build b/meson.build index 46f5a25..64e121f 100644 --- a/meson.build +++ b/meson.build @@ -11,6 +11,7 @@ project( sources = [ 'src/constraints.c', 'src/main.c', + 'src/solver/last_remaining.c', 'src/solver/single_occurence.c', 'src/solver/solve.c', 'src/solver/update_sets.c', diff --git a/src/solver/internals.h b/src/solver/internals.h index a052ed5..eca7af0 100644 --- a/src/solver/internals.h +++ b/src/solver/internals.h @@ -7,5 +7,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); #endif /* !INTERNALS_H */ diff --git a/src/solver/last_remaining.c b/src/solver/last_remaining.c new file mode 100644 index 0000000..85217a6 --- /dev/null +++ b/src/solver/last_remaining.c @@ -0,0 +1,76 @@ +#include "internals.h" + +#include + +#include "sudoku.h" + +static bool last_line(struct sudoku *grid, size_t i, size_t j) { + size_t numbers = 9 * 10 / 2; // Sum from 1 to 9 + size_t remaining = 9; + for (size_t c = 0; c < 9; ++c) { + if (c == j) + continue; + numbers -= grid->grid[i][c]; + remaining -= grid->grid[i][c] != 0; + } + + if (remaining != 1) + return false; + + grid->grid[i][j] = numbers; + return true; +} + +static bool last_column(struct sudoku *grid, size_t i, size_t j) { + size_t numbers = 9 * 10 / 2; // Sum from 1 to 9 + size_t remaining = 9; + for (size_t l = 0; l < 9; ++l) { + if (l == i) + continue; + numbers -= grid->grid[l][j]; + remaining -= grid->grid[l][j] != 0; + } + + if (remaining != 1) + return false; + + grid->grid[i][j] = numbers; + return true; +} + +static bool last_square(struct sudoku *grid, size_t i, size_t j) { + const size_t x = i / 3; + const size_t y = j / 3; + + size_t numbers = 9 * 10 / 2; // Sum from 1 to 9 + size_t remaining = 9; + for (size_t l = 3 * x; l < 3 * (x + 1); ++l) { + for (size_t c = 3 * y; c < 3 * (y + 1); ++c) { + if ((l == i) && (c == j)) + continue; + numbers -= grid->grid[l][c]; + remaining -= grid->grid[l][c] != 0; + } + } + + if (remaining != 1) + return false; + + grid->grid[i][j] = numbers; + return true; +} + +bool last_remaining(struct sudoku *grid) { + bool changed = false; + + for (size_t i = 0; i < 9; ++i) { + for (size_t j = 0; j < 9; ++j) { + if (grid->grid[i][j] != 0) + continue; + changed |= last_line(grid, i, j) || last_column(grid, i, j) + || last_square(grid, i, j); + } + } + + return changed; +} diff --git a/src/solver/solve.c b/src/solver/solve.c index 700eb60..d6d6932 100644 --- a/src/solver/solve.c +++ b/src/solver/solve.c @@ -29,6 +29,7 @@ bool solve(struct sudoku *grid) { changed |= update_sets(grid, possibilities); changed |= single_occurrence(grid, possibilities); + changed |= last_remaining(grid); } while (changed); return solved(grid);