diff --git a/solve.c b/solve.c index cdc7b22..a0d1420 100644 --- a/solve.c +++ b/solve.c @@ -20,89 +20,34 @@ #include -struct match { - unsigned row; - unsigned col; - unsigned val; -}; - -struct cellref { - unsigned row, col; - struct cellstate *state; -}; - -enum apply_res { ERROR, NO_MATCH, MATCH }; - -typedef struct cellref cellgroup[NDIGITS]; -typedef bool (*rulefn)(cellgroup *group, struct match *match_out); - -static bool one_place_for_digit(cellgroup *group, struct match *match_out) -{ - for (unsigned val = 0; val < NDIGITS; ++val) { - unsigned n = 0, row = NDIGITS, col = NDIGITS; - for (unsigned i = 0; i < NDIGITS; ++i) { - if (!(*group)[i].state->det && (*group)[i].state->pvals[val]) { - row = (*group)[i].row; - col = (*group)[i].col; - ++n; - if (n > 1) - break; - } - } - - if (n == 1) { - match_out->row = row; - match_out->col = col; - match_out->val = val; - return true; - } - } - - return false; -} - -static const rulefn rules[] = { - &one_place_for_digit, -}; -static const unsigned nrules = sizeof(rules) / sizeof(rules[0]); - -static enum apply_res apply_rules(struct sudoku *sud, cellgroup *group) -{ - struct match m; - bool matched = false; - for (unsigned i = 0; i < nrules; ++i) { - if (!rules[i](group, &m)) - continue; - if (!update(sud, m.row, m.col, m.val)) - return ERROR; - matched = true; - } - return matched ? MATCH : NO_MATCH; -} - int solve(struct sudoku *sud) { - cellgroup group = { 0 }; - unsigned r, c, n; + unsigned r, c, n, val, np, pr, pc; bool match; - enum apply_res res; for (n = 0;; ++n) { match = false; - /* Apply rules to each row. */ + /* Check if only one place a value can go on each row. */ for (r = 0; r < NDIGITS; ++r) { - for (c = 0; c < NDIGITS; ++c) { - group[c].row = r; - group[c].col = c; - group[c].state = &sud->cells[r][c]; - } + for (val = 0; val < NDIGITS; ++val) { + np = 0; + for (c = 0; c < NDIGITS; ++c) { + if (!sud->cells[r][c].det && sud->cells[r][c].pvals[val]) { + pr = r; + pc = c; + ++np; + if (np > 1) + break; + } + } - res = apply_rules(sud, &group); - if (res == ERROR) - return -1; - else if (res == MATCH) - match = true; + if (np == 1) { + if (update(sud, pr, pc, val) != OK) + return -1; + match = true; + } + } } /* Exit if no matches. */