diff options
| author | Simon Tatham <anakin@pobox.com> | 2023-02-05 10:29:42 +0000 |
|---|---|---|
| committer | Simon Tatham <anakin@pobox.com> | 2023-02-05 10:41:17 +0000 |
| commit | 5030d87903191d581586ecda2382ad5bcd70f63d (patch) | |
| tree | 16723a72976b9b1699b923d1c991e8cf7b9f9eec /latin.c | |
| parent | 517b14e666b0b71fc0bcd5da1b22cdc90d3434c9 (diff) | |
| download | puzzles-5030d87903191d581586ecda2382ad5bcd70f63d.zip puzzles-5030d87903191d581586ecda2382ad5bcd70f63d.tar.gz puzzles-5030d87903191d581586ecda2382ad5bcd70f63d.tar.bz2 puzzles-5030d87903191d581586ecda2382ad5bcd70f63d.tar.xz | |
latin_solver_alloc: handle clashing numbers in input grid.
In the setup phase of the centralised latin.c solver, we start by
going over the input grid containing already-placed clue numbers, and
calling latin_solver_place to enter each on into the solver's data
structure. This has the side effect of ruling out each number from the
rest of the row and column, and _also_ checking by assertion that the
number being placed is not ruled out.
Those are a bad combination, because it means that if you give an
obviously inconsistent input grid to latin_solver_alloc (e.g. with two
identical numbers in a row already), it will fail an assertion. In
that situation, you want the solver run as a whole to return
diff_impossible so that the error is reported cleanly.
This assertion failure could be provoked by giving either Towers or
Group a manually-constructed game description inconsistent in that
way, and hitting Solve. Worse, it could be provoked during live play
in Unequal, by filling in a number clashing with a clue and then
pressing 'h' to get hints.
Diffstat (limited to 'latin.c')
| -rw-r--r-- | latin.c | 47 |
1 files changed, 30 insertions, 17 deletions
@@ -563,7 +563,7 @@ void latin_solver_free_scratch(struct latin_solver_scratch *scratch) sfree(scratch); } -void latin_solver_alloc(struct latin_solver *solver, digit *grid, int o) +bool latin_solver_alloc(struct latin_solver *solver, digit *grid, int o) { int x, y; @@ -577,14 +577,23 @@ void latin_solver_alloc(struct latin_solver *solver, digit *grid, int o) memset(solver->row, 0, o*o); memset(solver->col, 0, o*o); - for (x = 0; x < o; x++) - for (y = 0; y < o; y++) - if (grid[y*o+x]) - latin_solver_place(solver, x, y, grid[y*o+x]); - #ifdef STANDALONE_SOLVER solver->names = NULL; #endif + + for (x = 0; x < o; x++) { + for (y = 0; y < o; y++) { + int n = grid[y*o+x]; + if (n) { + if (cube(x, y, n)) + latin_solver_place(solver, x, y, n); + else + return false; /* puzzle is already inconsistent */ + } + } + } + + return true; } void latin_solver_free(struct latin_solver *solver) @@ -810,15 +819,17 @@ static int latin_solver_recurse } else { newctx = ctx; } - latin_solver_alloc(&subsolver, outgrid, o); #ifdef STANDALONE_SOLVER subsolver.names = solver->names; #endif - ret = latin_solver_top(&subsolver, diff_recursive, - diff_simple, diff_set_0, diff_set_1, - diff_forcing, diff_recursive, - usersolvers, valid, newctx, - ctxnew, ctxfree); + if (latin_solver_alloc(&subsolver, outgrid, o)) + ret = latin_solver_top(&subsolver, diff_recursive, + diff_simple, diff_set_0, diff_set_1, + diff_forcing, diff_recursive, + usersolvers, valid, newctx, + ctxnew, ctxfree); + else + ret = diff_impossible; latin_solver_free(&subsolver); if (ctxnew) ctxfree(newctx); @@ -1059,11 +1070,13 @@ int latin_solver(digit *grid, int o, int maxdiff, struct latin_solver solver; int diff; - latin_solver_alloc(&solver, grid, o); - diff = latin_solver_main(&solver, maxdiff, - diff_simple, diff_set_0, diff_set_1, - diff_forcing, diff_recursive, - usersolvers, valid, ctx, ctxnew, ctxfree); + if (latin_solver_alloc(&solver, grid, o)) + diff = latin_solver_main(&solver, maxdiff, + diff_simple, diff_set_0, diff_set_1, + diff_forcing, diff_recursive, + usersolvers, valid, ctx, ctxnew, ctxfree); + else + diff = diff_impossible; latin_solver_free(&solver); return diff; } |