From 48b0ef1cf22ec37927116ac83ea7c7cfc1f9083e Mon Sep 17 00:00:00 2001 From: Franklin Wei Date: Thu, 25 Jun 2020 14:44:33 -0400 Subject: puzzles: resync with upstream This brings the upstream version to 9aa7b7c (with some of my changes as well). Change-Id: I5bf8a3e0b8672d82cb1bf34afc07adbe12a3ac53 --- apps/plugins/puzzles/src/keen.c | 88 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) (limited to 'apps/plugins/puzzles/src/keen.c') diff --git a/apps/plugins/puzzles/src/keen.c b/apps/plugins/puzzles/src/keen.c index baa1d81802..70e3e5432c 100644 --- a/apps/plugins/puzzles/src/keen.c +++ b/apps/plugins/puzzles/src/keen.c @@ -591,6 +591,92 @@ 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 int transpose(int index, int w) +{ + 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) { int a = w*w; @@ -638,7 +724,7 @@ static int solver(int w, int *dsf, long *clues, digit *soln, int maxdiff) ret = latin_solver(soln, w, maxdiff, DIFF_EASY, DIFF_HARD, DIFF_EXTREME, DIFF_EXTREME, DIFF_UNREASONABLE, - keen_solvers, &ctx, NULL, NULL); + keen_solvers, keen_valid, &ctx, NULL, NULL); sfree(ctx.dscratch); sfree(ctx.iscratch); -- cgit v1.2.3