From 8110518c33c73ab88838bd537fa085e29b1f7c13 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 23 May 2020 09:20:49 +0100 Subject: [PATCH] Keen: fill in the latin.c validator function. This seems to make no difference that I can detect: a test generation run of the form 'keen --generate 1000 6du#12345' outputs an identical list of 1000 puzzle ids before and after. So the missing validation in this puzzle seems to have been benign. --- keen.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 2 deletions(-) diff --git a/keen.c b/keen.c index 4c6e330..70e3e54 100644 --- a/keen.c +++ b/keen.c @@ -591,9 +591,90 @@ static int solver_hard(struct latin_solver *solver, void *vctx) #define SOLVER(upper,title,func,lower) func, static usersolver_t const keen_solvers[] = { DIFFLIST(SOLVER) }; -static bool keen_valid(struct latin_solver *solver, void *ctx) +static int transpose(int index, int w) { - return true; /* FIXME */ + return (index % w) * w + (index / w); +} + +static bool keen_valid(struct latin_solver *solver, void *vctx) +{ + struct solver_ctx *ctx = (struct solver_ctx *)vctx; + int w = ctx->w; + int box, i; + + /* + * Iterate over each clue box and check it's satisfied. + */ + for (box = 0; box < ctx->nboxes; box++) { + int *sq = ctx->boxlist + ctx->boxes[box]; + int n = ctx->boxes[box+1] - ctx->boxes[box]; + long value = ctx->clues[box] & ~CMASK; + long op = ctx->clues[box] & CMASK; + bool fail = false; + + switch (op) { + case C_ADD: { + long sum = 0; + for (i = 0; i < n; i++) + sum += solver->grid[transpose(sq[i], w)]; + fail = (sum != value); + break; + } + + case C_MUL: { + long remaining = value; + for (i = 0; i < n; i++) { + if (remaining % solver->grid[transpose(sq[i], w)]) { + fail = true; + break; + } + remaining /= solver->grid[transpose(sq[i], w)]; + } + if (remaining != 1) + fail = true; + break; + } + + case C_SUB: + assert(n == 2); + if (value != labs(solver->grid[transpose(sq[0], w)] - + solver->grid[transpose(sq[1], w)])) + fail = true; + break; + + case C_DIV: { + int num, den; + assert(n == 2); + num = max(solver->grid[transpose(sq[0], w)], + solver->grid[transpose(sq[1], w)]); + den = min(solver->grid[transpose(sq[0], w)], + solver->grid[transpose(sq[1], w)]); + if (den * value != num) + fail = true; + break; + } + } + + if (fail) { +#ifdef STANDALONE_SOLVER + if (solver_show_working) { + printf("%*sclue at (%d,%d) is violated\n", + solver_recurse_depth*4, "", + sq[0]/w+1, sq[0]%w+1); + printf("%*s (%s clue with target %ld containing [", + solver_recurse_depth*4, "", + (op == C_ADD ? "addition" : op == C_SUB ? "subtraction": + op == C_MUL ? "multiplication" : "division"), value); + for (i = 0; i < n; i++) + printf(" %d", (int)solver->grid[transpose(sq[i], w)]); + printf(" ]\n"); + } +#endif + return false; + } + } + + return true; } static int solver(int w, int *dsf, long *clues, digit *soln, int maxdiff)