diff --git a/meson.build b/meson.build index ef8e833..0dc7f4e 100644 --- a/meson.build +++ b/meson.build @@ -11,11 +11,18 @@ project( sources = [ 'src/constraints.c', 'src/main.c', + 'src/solver/solve.c', + 'src/solver/update_sets.c', 'src/sudoku.c', ] +incdir = include_directories( + 'src', +) + executable( 'sudoku', sources : sources, c_args : '-D_POSIX_C_SOURCE=200809L', + include_directories : incdir, ) diff --git a/src/solver/internals.h b/src/solver/internals.h new file mode 100644 index 0000000..0ebba42 --- /dev/null +++ b/src/solver/internals.h @@ -0,0 +1,10 @@ +#ifndef INTERNALS_H +#define INTERNALS_H + +#include + +struct sudoku; + +bool update_sets(const struct sudoku *grid, bool possibilities[9][9][9]); + +#endif /* !INTERNALS_H */ diff --git a/src/solver/solve.c b/src/solver/solve.c new file mode 100644 index 0000000..15125ea --- /dev/null +++ b/src/solver/solve.c @@ -0,0 +1,34 @@ +#include "solve.h" + +#include + +#include "constraints.h" +#include "internals.h" +#include "sudoku.h" + +static void init_possibilities(bool possibilities[9][9][9]) { + for (size_t i = 0; i < 9; ++i) { + for (size_t j = 0; j < 9; ++j) { + for (size_t n = 0; n < 9; ++n) { + possibilities[i][j][n] = true; + } + } + } +} + +bool solve(struct sudoku *grid) { + if (!grid) + return false; + + bool possibilities[9][9][9]; + init_possibilities(possibilities); + + bool changed; + do { + changed = false; + + changed |= update_sets(grid, possibilities); + } while (changed); + + return solved(grid); +} diff --git a/src/solver/solve.h b/src/solver/solve.h new file mode 100644 index 0000000..0f3028c --- /dev/null +++ b/src/solver/solve.h @@ -0,0 +1,10 @@ +#ifndef SOLVE_H +#define SOLVE_H + +#include + +struct sudoku; + +bool solve(struct sudoku *grid); + +#endif /* !SOLVE_H */ diff --git a/src/solver/update_sets.c b/src/solver/update_sets.c new file mode 100644 index 0000000..e550fa9 --- /dev/null +++ b/src/solver/update_sets.c @@ -0,0 +1,85 @@ +#include "internals.h" + +#include + +#include "sudoku.h" + +static bool ensure_unique(bool possibilities[9][9][9], size_t i, size_t j, + int num) { + bool changed = false; + + for (int n = 0; n < 9; ++n) { + if (n == num) + continue; + changed |= possibilities[i][j][n]; + possibilities[i][j][n] = false; + } + + return changed; +} + +static bool update_line(bool possibilities[9][9][9], size_t i, size_t j, + int num) { + bool changed = false; + + for (size_t c = 0; c < 9; ++c) { + if (c == j) + continue; + changed |= possibilities[i][c][num]; + possibilities[i][c][num] = false; + } + + return changed; +} + +static bool update_column(bool possibilities[9][9][9], size_t i, size_t j, + int num) { + bool changed = false; + + for (size_t l = 0; l < 9; ++l) { + if (l == i) + continue; + changed |= possibilities[l][j][num]; + possibilities[l][j][num] = false; + } + + return changed; +} + +static bool update_square(bool possibilities[9][9][9], size_t i, size_t j, + int num) { + bool changed = false; + + const size_t x = i / 3; + const size_t y = j / 3; + + 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; + changed |= possibilities[l][c][num]; + possibilities[l][c][num] = false; + } + } + + return changed; +} + +bool update_sets(const 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) { + const int val = grid->grid[i][j]; + if (val == 0) + continue; + + changed |= ensure_unique(possibilities, i, j, val - 1); + changed |= update_line(possibilities, i, j, val - 1); + changed |= update_column(possibilities, i, j, val - 1); + changed |= update_square(possibilities, i, j, val - 1); + } + } + + return changed; +}