sudoku: solver: add last remaining heuristic
This commit is contained in:
parent
18bb94836e
commit
b17cb8d84c
|
@ -11,6 +11,7 @@ project(
|
||||||
sources = [
|
sources = [
|
||||||
'src/constraints.c',
|
'src/constraints.c',
|
||||||
'src/main.c',
|
'src/main.c',
|
||||||
|
'src/solver/last_remaining.c',
|
||||||
'src/solver/single_occurence.c',
|
'src/solver/single_occurence.c',
|
||||||
'src/solver/solve.c',
|
'src/solver/solve.c',
|
||||||
'src/solver/update_sets.c',
|
'src/solver/update_sets.c',
|
||||||
|
|
|
@ -7,5 +7,6 @@ struct sudoku;
|
||||||
|
|
||||||
bool update_sets(const struct sudoku *grid, bool possibilities[9][9][9]);
|
bool update_sets(const struct sudoku *grid, bool possibilities[9][9][9]);
|
||||||
bool single_occurrence(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 */
|
#endif /* !INTERNALS_H */
|
||||||
|
|
76
src/solver/last_remaining.c
Normal file
76
src/solver/last_remaining.c
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
#include "internals.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -29,6 +29,7 @@ bool solve(struct sudoku *grid) {
|
||||||
|
|
||||||
changed |= update_sets(grid, possibilities);
|
changed |= update_sets(grid, possibilities);
|
||||||
changed |= single_occurrence(grid, possibilities);
|
changed |= single_occurrence(grid, possibilities);
|
||||||
|
changed |= last_remaining(grid);
|
||||||
} while (changed);
|
} while (changed);
|
||||||
|
|
||||||
return solved(grid);
|
return solved(grid);
|
||||||
|
|
Loading…
Reference in a new issue