diff --git a/meson.build b/meson.build index 0dc7f4e..46f5a25 100644 --- a/meson.build +++ b/meson.build @@ -11,6 +11,7 @@ project( sources = [ 'src/constraints.c', 'src/main.c', + 'src/solver/single_occurence.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 0ebba42..a052ed5 100644 --- a/src/solver/internals.h +++ b/src/solver/internals.h @@ -6,5 +6,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]); #endif /* !INTERNALS_H */ diff --git a/src/solver/single_occurence.c b/src/solver/single_occurence.c new file mode 100644 index 0000000..5e7d077 --- /dev/null +++ b/src/solver/single_occurence.c @@ -0,0 +1,92 @@ +#include "internals.h" + +#include + +#include "sudoku.h" + +static bool single_line(struct sudoku *grid, bool possibilities[9][9][9], + size_t i, size_t j) { + for (int n = 0; n < 9; ++n) { + if (!possibilities[i][j][n]) + continue; + + bool unique = true; + for (size_t c = 0; c < 9; ++c) { + if (c == j) + continue; + unique &= !possibilities[i][c][n]; + } + if (!unique) + continue; + + grid->grid[i][j] = n + 1; + return true; + } + + return false; +} + +static bool single_column(struct sudoku *grid, bool possibilities[9][9][9], + size_t i, size_t j) { + for (int n = 0; n < 9; ++n) { + if (!possibilities[i][j][n]) + continue; + + bool unique = true; + for (size_t l = 0; l < 9; ++l) { + if (l == i) + continue; + unique &= !possibilities[l][j][n]; + } + if (!unique) + continue; + + grid->grid[i][j] = n + 1; + return true; + } + + return false; +} + +static bool single_square(struct sudoku *grid, bool possibilities[9][9][9], + size_t i, size_t j) { + const size_t x = i / 3; + const size_t y = j / 3; + + for (int n = 0; n < 9; ++n) { + if (!possibilities[i][j][n]) + continue; + + bool unique = true; + 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; + unique &= !possibilities[i][c][n]; + } + } + if (!unique) + continue; + + grid->grid[i][j] = n + 1; + return true; + } + + return false; +} + +bool single_occurrence(struct sudoku *grid, bool possibilities[9][9][9]) { + 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 |= single_line(grid, possibilities, i, j) + || single_column(grid, possibilities, i, j) + || single_square(grid, possibilities, i, j); + } + } + + return changed; +} diff --git a/src/solver/solve.c b/src/solver/solve.c index 15125ea..700eb60 100644 --- a/src/solver/solve.c +++ b/src/solver/solve.c @@ -28,6 +28,7 @@ bool solve(struct sudoku *grid) { changed = false; changed |= update_sets(grid, possibilities); + changed |= single_occurrence(grid, possibilities); } while (changed); return solved(grid);