mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-20 23:51:29 -07:00
latin.c: call a user-provided validator function. [NFC]
I've only just realised that there's a false-positive bug in the latin.c solver framework. It's designed to solve puzzles in which the solution is a latin square but with some additional constraints provided by the individual puzzle, and so during solving, it runs a mixture of its own standard deduction functions that apply to any latin-square puzzle and extra functions provided by the client puzzle to do deductions based on the extra clues or constraints. But what happens if the _last_ move in the solving process is performed by one of the latin.c built-in methods, and it causes a violation of the client puzzle's extra constraints? Nothing will ever notice, and so the solver will report that the puzzle has a solution when it actually has none. An example is the Group game id 12i:m12b9a1zd9i6d10c3y2l11q4r . This was reported by 'groupsolver -g' as being ambiguous. But if you look at the two 'solutions' reported in the verbose diagnostics, one of them is arrant nonsense: it has no identity element at all, and therefore, it fails associativity all over the place. Actually that puzzle _does_ have a unique solution. This bug has been around for ages, and nobody has reported a problem. For recursive solving, that's not much of a surprise, because it would cause a spurious accusation of ambiguity, so that at generation time some valid puzzles would be wrongly discarded, and you'd never see them. But at non-recursive levels, I can't see a reason why this bug _couldn't_ have led one of the games to present an actually impossible puzzle believing it to be soluble. Possibly this never came up because the other clients of latin.c are more forgiving of this error in some way. For example, they might all be very likely to use their extra clues early in the solving process, so that the requirements are already baked in by the time the final grid square is filled. I don't know! Anyway. The fix is to introduce last-minute client-side validation: whenever the centralised latin_solver thinks it's come up with a filled grid, it should present it to a puzzle-specific validator function and check that it's _really_ a legal solution. This commit does the plumbing for all of that: it introduces the new validator function as one of the many parameters to latin_solver, and arranges to call it in an appropriate way during the solving process. But all the per-puzzle validation functions are empty, for the moment.
This commit is contained in:
7
towers.c
7
towers.c
@ -574,6 +574,11 @@ static int solver_hard(struct latin_solver *solver, void *vctx)
|
||||
#define SOLVER(upper,title,func,lower) func,
|
||||
static usersolver_t const towers_solvers[] = { DIFFLIST(SOLVER) };
|
||||
|
||||
static bool towers_valid(struct latin_solver *solver, void *ctx)
|
||||
{
|
||||
return true; /* FIXME */
|
||||
}
|
||||
|
||||
static int solver(int w, int *clues, digit *soln, int maxdiff)
|
||||
{
|
||||
int ret;
|
||||
@ -589,7 +594,7 @@ static int solver(int w, int *clues, digit *soln, int maxdiff)
|
||||
ret = latin_solver(soln, w, maxdiff,
|
||||
DIFF_EASY, DIFF_HARD, DIFF_EXTREME,
|
||||
DIFF_EXTREME, DIFF_UNREASONABLE,
|
||||
towers_solvers, &ctx, NULL, NULL);
|
||||
towers_solvers, towers_valid, &ctx, NULL, NULL);
|
||||
|
||||
sfree(ctx.iscratch);
|
||||
sfree(ctx.dscratch);
|
||||
|
Reference in New Issue
Block a user