sudoku: solver: add basic possibilities reducer
This commit is contained in:
parent
06bba6ca68
commit
0fcee5bc0c
|
@ -11,11 +11,18 @@ project(
|
||||||
sources = [
|
sources = [
|
||||||
'src/constraints.c',
|
'src/constraints.c',
|
||||||
'src/main.c',
|
'src/main.c',
|
||||||
|
'src/solver/solve.c',
|
||||||
|
'src/solver/update_sets.c',
|
||||||
'src/sudoku.c',
|
'src/sudoku.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
incdir = include_directories(
|
||||||
|
'src',
|
||||||
|
)
|
||||||
|
|
||||||
executable(
|
executable(
|
||||||
'sudoku',
|
'sudoku',
|
||||||
sources : sources,
|
sources : sources,
|
||||||
c_args : '-D_POSIX_C_SOURCE=200809L',
|
c_args : '-D_POSIX_C_SOURCE=200809L',
|
||||||
|
include_directories : incdir,
|
||||||
)
|
)
|
||||||
|
|
10
src/solver/internals.h
Normal file
10
src/solver/internals.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef INTERNALS_H
|
||||||
|
#define INTERNALS_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
struct sudoku;
|
||||||
|
|
||||||
|
bool update_sets(const struct sudoku *grid, bool possibilities[9][9][9]);
|
||||||
|
|
||||||
|
#endif /* !INTERNALS_H */
|
34
src/solver/solve.c
Normal file
34
src/solver/solve.c
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#include "solve.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
10
src/solver/solve.h
Normal file
10
src/solver/solve.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef SOLVE_H
|
||||||
|
#define SOLVE_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
struct sudoku;
|
||||||
|
|
||||||
|
bool solve(struct sudoku *grid);
|
||||||
|
|
||||||
|
#endif /* !SOLVE_H */
|
85
src/solver/update_sets.c
Normal file
85
src/solver/update_sets.c
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
#include "internals.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
Loading…
Reference in a new issue