diff --git a/sud.c b/sud.c index 5b6d331..aabe37e 100644 --- a/sud.c +++ b/sud.c @@ -171,3 +171,64 @@ void print(const struct sudoku *sud) putchar('\n'); } } + +static void zerocounts(unsigned counts[NDIGITS]) +{ + for (unsigned i = 0; i < NDIGITS; ++i) + counts[i] = 0; +} + +static bool checkcounts(unsigned counts[NDIGITS]) +{ + for (unsigned i = 0; i < NDIGITS; ++i) { + if (counts[i] != 1) + return false; + } + return true; +} + +enum check_res check(const struct sudoku *sud) +{ + unsigned r, c, i, j, digitcounts[NDIGITS]; + + /* Check each row. */ + for (r = 0; r < NDIGITS; ++r) { + zerocounts(digitcounts); + for (c = 0; c < NDIGITS; ++c) { + if (!sud->cells[r][c].det) + return INCOMPLETE; + ++digitcounts[sud->cells[r][c].val]; + } + if (!checkcounts(digitcounts)) + return INCORRECT; + } + + /* Check each column. */ + for (c = 0; c < NDIGITS; ++c) { + zerocounts(digitcounts); + for (r = 0; r < NDIGITS; ++r) { + if (!sud->cells[r][c].det) + return INCOMPLETE; + ++digitcounts[sud->cells[r][c].val]; + } + if (!checkcounts(digitcounts)) + return INCORRECT; + } + + /* Check each segment. */ + for (i = 0; i < NDIGITS; ++i) { + zerocounts(digitcounts); + for (j = 0; j < NDIGITS; ++j) { + r = 3 * (i / 3) + j / 3; + c = 3 * (i % 3) + j % 3; + if (!sud->cells[r][c].det) + return INCOMPLETE; + ++digitcounts[sud->cells[r][c].val]; + } + if (!checkcounts(digitcounts)) + return INCORRECT; + } + + /* If we've got this far, all is well. */ + return SOLVED; +} diff --git a/sud.h b/sud.h index 40178a7..df07d4b 100644 --- a/sud.h +++ b/sud.h @@ -22,7 +22,7 @@ #include #define SEGLEN 3 -#define NDIGITS 9 +#define NDIGITS (SEGLEN * SEGLEN) struct cellstate { bool det; @@ -38,6 +38,8 @@ struct sudoku { enum update_res { NOT_ALLOWED, ALREADY_DET, OK }; +enum check_res { INCOMPLETE, INCORRECT, SOLVED }; + /** * Populate the sudoku with some random values. */ @@ -57,4 +59,10 @@ update(struct sudoku *sud, unsigned r, unsigned c, unsigned val); */ void print(const struct sudoku *sud); +/** + * Determine whether the sudoku has been solved correctly, contains + * invalid choices or is incomplete. + */ +enum check_res check(const struct sudoku *sud); + #endif