ref: 13d7ff6ae5fd746461a4ef1cd01a6b5255692afb
parent: a7b220ff9a6b3cc4669565f9221071561f965f35
author: Simon Tatham <anakin@pobox.com>
date: Tue Jan 5 18:40:40 EST 2010
Add a facility in the latin.c solver diagnostics to allow a puzzle to call the digit values by custom names. [originally from svn r8811]
--- a/latin.c
+++ b/latin.c
@@ -16,6 +16,12 @@
* Solver.
*/
+static int latin_solver_top(struct latin_solver *solver, int maxdiff,
+ int diff_simple, int diff_set_0, int diff_set_1,
+ int diff_forcing, int diff_recursive,
+ usersolver_t const *usersolvers, void *ctx,
+ ctxnew_t ctxnew, ctxfree_t ctxfree);
+
#ifdef STANDALONE_SOLVER
int solver_show_working, solver_recurse_depth;
#endif
@@ -72,6 +78,9 @@
)
{
int o = solver->o;
+#ifdef STANDALONE_SOLVER
+ char **names = solver->names;
+#endif
int fpos, m, i;
/*
@@ -103,8 +112,9 @@
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
- printf(":\n%*s placing %d at (%d,%d)\n",
- solver_recurse_depth*4, "", n, x+1, YUNTRANS(y)+1);
+ printf(":\n%*s placing %s at (%d,%d)\n",
+ solver_recurse_depth*4, "", names[n-1],
+ x+1, YUNTRANS(y)+1);
}
#endif
latin_solver_place(solver, x, y, n);
@@ -145,6 +155,9 @@
)
{
int o = solver->o;
+#ifdef STANDALONE_SOLVER
+ char **names = solver->names;
+#endif
int i, j, n, count;
unsigned char *grid = scratch->grid;
unsigned char *rowidx = scratch->rowidx;
@@ -292,9 +305,9 @@
px = py / o;
py %= o;
- printf("%*s ruling out %d at (%d,%d)\n",
+ printf("%*s ruling out %s at (%d,%d)\n",
solver_recurse_depth*4, "",
- pn, px+1, YUNTRANS(py)+1);
+ names[pn-1], px+1, YUNTRANS(py)+1);
}
#endif
progress = TRUE;
@@ -365,6 +378,9 @@
struct latin_solver_scratch *scratch)
{
int o = solver->o;
+#ifdef STANDALONE_SOLVER
+ char **names = solver->names;
+#endif
int *bfsqueue = scratch->bfsqueue;
#ifdef STANDALONE_SOLVER
int *bfsprev = scratch->bfsprev;
@@ -485,8 +501,9 @@
if (solver_show_working) {
char *sep = "";
int xl, yl;
- printf("%*sforcing chain, %d at ends of ",
- solver_recurse_depth*4, "", orign);
+ printf("%*sforcing chain, %s at ends of ",
+ solver_recurse_depth*4, "",
+ names[orign-1]);
xl = xx;
yl = yy;
while (1) {
@@ -499,9 +516,10 @@
xl %= o;
sep = "-";
}
- printf("\n%*s ruling out %d at (%d,%d)\n",
+ printf("\n%*s ruling out %s at (%d,%d)\n",
solver_recurse_depth*4, "",
- orign, xt+1, YUNTRANS(yt)+1);
+ names[orign-1],
+ xt+1, YUNTRANS(yt)+1);
}
#endif
cube(xt, yt, orign) = FALSE;
@@ -563,6 +581,10 @@
for (y = 0; y < o; y++)
if (grid[y*o+x])
latin_solver_place(solver, x, YTRANS(y), grid[y*o+x]);
+
+#ifdef STANDALONE_SOLVER
+ solver->names = NULL;
+#endif
}
void latin_solver_free(struct latin_solver *solver)
@@ -575,6 +597,10 @@
int latin_solver_diff_simple(struct latin_solver *solver)
{
int x, y, n, ret, o = solver->o;
+#ifdef STANDALONE_SOLVER
+ char **names = solver->names;
+#endif
+
/*
* Row-wise positional elimination.
*/
@@ -584,7 +610,8 @@
ret = latin_solver_elim(solver, cubepos(0,y,n), o*o
#ifdef STANDALONE_SOLVER
, "positional elimination,"
- " %d in row %d", n, YUNTRANS(y)+1
+ " %s in row %d", names[n-1],
+ YUNTRANS(y)+1
#endif
);
if (ret != 0) return ret;
@@ -598,7 +625,7 @@
ret = latin_solver_elim(solver, cubepos(x,0,n), o
#ifdef STANDALONE_SOLVER
, "positional elimination,"
- " %d in column %d", n, x+1
+ " %s in column %d", names[n-1], x+1
#endif
);
if (ret != 0) return ret;
@@ -626,6 +653,9 @@
int extreme)
{
int x, y, n, ret, o = solver->o;
+#ifdef STANDALONE_SOLVER
+ char **names = solver->names;
+#endif
if (!extreme) {
/*
@@ -658,7 +688,8 @@
for (n = 1; n <= o; n++) {
ret = latin_solver_set(solver, scratch, cubepos(0,0,n), o*o, o
#ifdef STANDALONE_SOLVER
- , "positional set elimination, number %d", n
+ , "positional set elimination on %s",
+ names[n-1]
#endif
);
if (ret != 0) return ret;
@@ -685,6 +716,9 @@
{
int best, bestcount;
int o = solver->o, x, y, n;
+#ifdef STANDALONE_SOLVER
+ char **names = solver->names;
+#endif
best = -1;
bestcount = o+1;
@@ -745,7 +779,7 @@
printf("%*srecursing on (%d,%d) [",
solver_recurse_depth*4, "", x+1, y+1);
for (i = 0; i < j; i++) {
- printf("%s%d", sep, list[i]);
+ printf("%s%s", sep, names[list[i]-1]);
sep = " or ";
}
printf("]\n");
@@ -759,6 +793,7 @@
for (i = 0; i < j; i++) {
int ret;
void *newctx;
+ struct latin_solver subsolver;
memcpy(outgrid, ingrid, o*o);
outgrid[y*o+x] = list[i];
@@ -765,8 +800,8 @@
#ifdef STANDALONE_SOLVER
if (solver_show_working)
- printf("%*sguessing %d at (%d,%d)\n",
- solver_recurse_depth*4, "", list[i], x+1, y+1);
+ printf("%*sguessing %s at (%d,%d)\n",
+ solver_recurse_depth*4, "", names[list[i]-1], x+1, y+1);
solver_recurse_depth++;
#endif
@@ -775,10 +810,15 @@
} else {
newctx = ctx;
}
- ret = latin_solver(outgrid, o, diff_recursive,
- diff_simple, diff_set_0, diff_set_1,
- diff_forcing, diff_recursive,
- usersolvers, newctx, ctxnew, ctxfree);
+ latin_solver_alloc(&subsolver, outgrid, o);
+#ifdef STANDALONE_SOLVER
+ subsolver.names = solver->names;
+#endif
+ ret = latin_solver_top(&subsolver, diff_recursive,
+ diff_simple, diff_set_0, diff_set_1,
+ diff_forcing, diff_recursive,
+ usersolvers, newctx, ctxnew, ctxfree);
+ latin_solver_free(&subsolver);
if (ctxnew)
ctxfree(newctx);
@@ -785,8 +825,8 @@
#ifdef STANDALONE_SOLVER
solver_recurse_depth--;
if (solver_show_working) {
- printf("%*sretracting %d at (%d,%d)\n",
- solver_recurse_depth*4, "", list[i], x+1, y+1);
+ printf("%*sretracting %s at (%d,%d)\n",
+ solver_recurse_depth*4, "", names[list[i]-1], x+1, y+1);
}
#endif
/* we recurse as deep as we can, so we should never find
@@ -836,11 +876,11 @@
}
}
-int latin_solver_main(struct latin_solver *solver, int maxdiff,
- int diff_simple, int diff_set_0, int diff_set_1,
- int diff_forcing, int diff_recursive,
- usersolver_t const *usersolvers, void *ctx,
- ctxnew_t ctxnew, ctxfree_t ctxfree)
+static int latin_solver_top(struct latin_solver *solver, int maxdiff,
+ int diff_simple, int diff_set_0, int diff_set_1,
+ int diff_forcing, int diff_recursive,
+ usersolver_t const *usersolvers, void *ctx,
+ ctxnew_t ctxnew, ctxfree_t ctxfree)
{
struct latin_solver_scratch *scratch = latin_solver_new_scratch(solver);
int ret, diff = diff_simple;
@@ -934,6 +974,48 @@
#endif
latin_solver_free_scratch(scratch);
+
+ return diff;
+}
+
+int latin_solver_main(struct latin_solver *solver, int maxdiff,
+ int diff_simple, int diff_set_0, int diff_set_1,
+ int diff_forcing, int diff_recursive,
+ usersolver_t const *usersolvers, void *ctx,
+ ctxnew_t ctxnew, ctxfree_t ctxfree)
+{
+ int diff;
+#ifdef STANDALONE_SOLVER
+ int o = solver->o;
+ char *text = NULL, **names = NULL;
+#endif
+
+#ifdef STANDALONE_SOLVER
+ if (!solver->names) {
+ char *p;
+ int i;
+
+ text = snewn(40 * o, char);
+ p = text;
+
+ solver->names = snewn(o, char *);
+
+ for (i = 0; i < o; i++) {
+ solver->names[i] = p;
+ p += 1 + sprintf(p, "%d", i+1);
+ }
+ }
+#endif
+
+ diff = latin_solver_top(solver, maxdiff,
+ diff_simple, diff_set_0, diff_set_1,
+ diff_forcing, diff_recursive,
+ usersolvers, ctx, ctxnew, ctxfree);
+
+#ifdef STANDALONE_SOLVER
+ sfree(names);
+ sfree(text);
+#endif
return diff;
}
--- a/latin.h
+++ b/latin.h
@@ -19,6 +19,10 @@
unsigned char *row; /* o^2: row[y*cr+n-1] TRUE if n is in row y */
unsigned char *col; /* o^2: col[x*cr+n-1] TRUE if n is in col x */
+
+#ifdef STANDALONE_SOLVER
+ char **names; /* o: names[n-1] gives name of 'digit' n */
+#endif
};
#define cubepos(x,y,n) (((x)*solver->o+(y))*solver->o+(n)-1)
#define cube(x,y,n) (solver->cube[cubepos(x,y,n)])