ref: 8110518c33c73ab88838bd537fa085e29b1f7c13
parent: 6285c44610cda5146b11fb1fcda45e488a5504de
author: Simon Tatham <anakin@pobox.com>
date: Sat May 23 05:20:49 EDT 2020
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.
--- a/keen.c
+++ b/keen.c
@@ -591,9 +591,90 @@
#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)