summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/src/keen.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/puzzles/src/keen.c')
-rw-r--r--apps/plugins/puzzles/src/keen.c88
1 files changed, 87 insertions, 1 deletions
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)
591#define SOLVER(upper,title,func,lower) func, 591#define SOLVER(upper,title,func,lower) func,
592static usersolver_t const keen_solvers[] = { DIFFLIST(SOLVER) }; 592static usersolver_t const keen_solvers[] = { DIFFLIST(SOLVER) };
593 593
594static int transpose(int index, int w)
595{
596 return (index % w) * w + (index / w);
597}
598
599static bool keen_valid(struct latin_solver *solver, void *vctx)
600{
601 struct solver_ctx *ctx = (struct solver_ctx *)vctx;
602 int w = ctx->w;
603 int box, i;
604
605 /*
606 * Iterate over each clue box and check it's satisfied.
607 */
608 for (box = 0; box < ctx->nboxes; box++) {
609 int *sq = ctx->boxlist + ctx->boxes[box];
610 int n = ctx->boxes[box+1] - ctx->boxes[box];
611 long value = ctx->clues[box] & ~CMASK;
612 long op = ctx->clues[box] & CMASK;
613 bool fail = false;
614
615 switch (op) {
616 case C_ADD: {
617 long sum = 0;
618 for (i = 0; i < n; i++)
619 sum += solver->grid[transpose(sq[i], w)];
620 fail = (sum != value);
621 break;
622 }
623
624 case C_MUL: {
625 long remaining = value;
626 for (i = 0; i < n; i++) {
627 if (remaining % solver->grid[transpose(sq[i], w)]) {
628 fail = true;
629 break;
630 }
631 remaining /= solver->grid[transpose(sq[i], w)];
632 }
633 if (remaining != 1)
634 fail = true;
635 break;
636 }
637
638 case C_SUB:
639 assert(n == 2);
640 if (value != labs(solver->grid[transpose(sq[0], w)] -
641 solver->grid[transpose(sq[1], w)]))
642 fail = true;
643 break;
644
645 case C_DIV: {
646 int num, den;
647 assert(n == 2);
648 num = max(solver->grid[transpose(sq[0], w)],
649 solver->grid[transpose(sq[1], w)]);
650 den = min(solver->grid[transpose(sq[0], w)],
651 solver->grid[transpose(sq[1], w)]);
652 if (den * value != num)
653 fail = true;
654 break;
655 }
656 }
657
658 if (fail) {
659#ifdef STANDALONE_SOLVER
660 if (solver_show_working) {
661 printf("%*sclue at (%d,%d) is violated\n",
662 solver_recurse_depth*4, "",
663 sq[0]/w+1, sq[0]%w+1);
664 printf("%*s (%s clue with target %ld containing [",
665 solver_recurse_depth*4, "",
666 (op == C_ADD ? "addition" : op == C_SUB ? "subtraction":
667 op == C_MUL ? "multiplication" : "division"), value);
668 for (i = 0; i < n; i++)
669 printf(" %d", (int)solver->grid[transpose(sq[i], w)]);
670 printf(" ]\n");
671 }
672#endif
673 return false;
674 }
675 }
676
677 return true;
678}
679
594static int solver(int w, int *dsf, long *clues, digit *soln, int maxdiff) 680static int solver(int w, int *dsf, long *clues, digit *soln, int maxdiff)
595{ 681{
596 int a = w*w; 682 int a = w*w;
@@ -638,7 +724,7 @@ static int solver(int w, int *dsf, long *clues, digit *soln, int maxdiff)
638 ret = latin_solver(soln, w, maxdiff, 724 ret = latin_solver(soln, w, maxdiff,
639 DIFF_EASY, DIFF_HARD, DIFF_EXTREME, 725 DIFF_EASY, DIFF_HARD, DIFF_EXTREME,
640 DIFF_EXTREME, DIFF_UNREASONABLE, 726 DIFF_EXTREME, DIFF_UNREASONABLE,
641 keen_solvers, &ctx, NULL, NULL); 727 keen_solvers, keen_valid, &ctx, NULL, NULL);
642 728
643 sfree(ctx.dscratch); 729 sfree(ctx.dscratch);
644 sfree(ctx.iscratch); 730 sfree(ctx.iscratch);