mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 08:01:30 -07:00
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]
This commit is contained in:
132
latin.c
132
latin.c
@ -16,6 +16,12 @@
|
|||||||
* Solver.
|
* 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
|
#ifdef STANDALONE_SOLVER
|
||||||
int solver_show_working, solver_recurse_depth;
|
int solver_show_working, solver_recurse_depth;
|
||||||
#endif
|
#endif
|
||||||
@ -72,6 +78,9 @@ int latin_solver_elim(struct latin_solver *solver, int start, int step
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
int o = solver->o;
|
int o = solver->o;
|
||||||
|
#ifdef STANDALONE_SOLVER
|
||||||
|
char **names = solver->names;
|
||||||
|
#endif
|
||||||
int fpos, m, i;
|
int fpos, m, i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -103,8 +112,9 @@ int latin_solver_elim(struct latin_solver *solver, int start, int step
|
|||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vprintf(fmt, ap);
|
vprintf(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
printf(":\n%*s placing %d at (%d,%d)\n",
|
printf(":\n%*s placing %s at (%d,%d)\n",
|
||||||
solver_recurse_depth*4, "", n, x+1, YUNTRANS(y)+1);
|
solver_recurse_depth*4, "", names[n-1],
|
||||||
|
x+1, YUNTRANS(y)+1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
latin_solver_place(solver, x, y, n);
|
latin_solver_place(solver, x, y, n);
|
||||||
@ -145,6 +155,9 @@ int latin_solver_set(struct latin_solver *solver,
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
int o = solver->o;
|
int o = solver->o;
|
||||||
|
#ifdef STANDALONE_SOLVER
|
||||||
|
char **names = solver->names;
|
||||||
|
#endif
|
||||||
int i, j, n, count;
|
int i, j, n, count;
|
||||||
unsigned char *grid = scratch->grid;
|
unsigned char *grid = scratch->grid;
|
||||||
unsigned char *rowidx = scratch->rowidx;
|
unsigned char *rowidx = scratch->rowidx;
|
||||||
@ -292,9 +305,9 @@ int latin_solver_set(struct latin_solver *solver,
|
|||||||
px = py / o;
|
px = py / o;
|
||||||
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, "",
|
solver_recurse_depth*4, "",
|
||||||
pn, px+1, YUNTRANS(py)+1);
|
names[pn-1], px+1, YUNTRANS(py)+1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
progress = TRUE;
|
progress = TRUE;
|
||||||
@ -365,6 +378,9 @@ int latin_solver_forcing(struct latin_solver *solver,
|
|||||||
struct latin_solver_scratch *scratch)
|
struct latin_solver_scratch *scratch)
|
||||||
{
|
{
|
||||||
int o = solver->o;
|
int o = solver->o;
|
||||||
|
#ifdef STANDALONE_SOLVER
|
||||||
|
char **names = solver->names;
|
||||||
|
#endif
|
||||||
int *bfsqueue = scratch->bfsqueue;
|
int *bfsqueue = scratch->bfsqueue;
|
||||||
#ifdef STANDALONE_SOLVER
|
#ifdef STANDALONE_SOLVER
|
||||||
int *bfsprev = scratch->bfsprev;
|
int *bfsprev = scratch->bfsprev;
|
||||||
@ -485,8 +501,9 @@ int latin_solver_forcing(struct latin_solver *solver,
|
|||||||
if (solver_show_working) {
|
if (solver_show_working) {
|
||||||
char *sep = "";
|
char *sep = "";
|
||||||
int xl, yl;
|
int xl, yl;
|
||||||
printf("%*sforcing chain, %d at ends of ",
|
printf("%*sforcing chain, %s at ends of ",
|
||||||
solver_recurse_depth*4, "", orign);
|
solver_recurse_depth*4, "",
|
||||||
|
names[orign-1]);
|
||||||
xl = xx;
|
xl = xx;
|
||||||
yl = yy;
|
yl = yy;
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -499,9 +516,10 @@ int latin_solver_forcing(struct latin_solver *solver,
|
|||||||
xl %= o;
|
xl %= o;
|
||||||
sep = "-";
|
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, "",
|
solver_recurse_depth*4, "",
|
||||||
orign, xt+1, YUNTRANS(yt)+1);
|
names[orign-1],
|
||||||
|
xt+1, YUNTRANS(yt)+1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
cube(xt, yt, orign) = FALSE;
|
cube(xt, yt, orign) = FALSE;
|
||||||
@ -563,6 +581,10 @@ void latin_solver_alloc(struct latin_solver *solver, digit *grid, int o)
|
|||||||
for (y = 0; y < o; y++)
|
for (y = 0; y < o; y++)
|
||||||
if (grid[y*o+x])
|
if (grid[y*o+x])
|
||||||
latin_solver_place(solver, x, YTRANS(y), 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)
|
void latin_solver_free(struct latin_solver *solver)
|
||||||
@ -575,6 +597,10 @@ void latin_solver_free(struct latin_solver *solver)
|
|||||||
int latin_solver_diff_simple(struct latin_solver *solver)
|
int latin_solver_diff_simple(struct latin_solver *solver)
|
||||||
{
|
{
|
||||||
int x, y, n, ret, o = solver->o;
|
int x, y, n, ret, o = solver->o;
|
||||||
|
#ifdef STANDALONE_SOLVER
|
||||||
|
char **names = solver->names;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Row-wise positional elimination.
|
* Row-wise positional elimination.
|
||||||
*/
|
*/
|
||||||
@ -584,7 +610,8 @@ int latin_solver_diff_simple(struct latin_solver *solver)
|
|||||||
ret = latin_solver_elim(solver, cubepos(0,y,n), o*o
|
ret = latin_solver_elim(solver, cubepos(0,y,n), o*o
|
||||||
#ifdef STANDALONE_SOLVER
|
#ifdef STANDALONE_SOLVER
|
||||||
, "positional elimination,"
|
, "positional elimination,"
|
||||||
" %d in row %d", n, YUNTRANS(y)+1
|
" %s in row %d", names[n-1],
|
||||||
|
YUNTRANS(y)+1
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
if (ret != 0) return ret;
|
if (ret != 0) return ret;
|
||||||
@ -598,7 +625,7 @@ int latin_solver_diff_simple(struct latin_solver *solver)
|
|||||||
ret = latin_solver_elim(solver, cubepos(x,0,n), o
|
ret = latin_solver_elim(solver, cubepos(x,0,n), o
|
||||||
#ifdef STANDALONE_SOLVER
|
#ifdef STANDALONE_SOLVER
|
||||||
, "positional elimination,"
|
, "positional elimination,"
|
||||||
" %d in column %d", n, x+1
|
" %s in column %d", names[n-1], x+1
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
if (ret != 0) return ret;
|
if (ret != 0) return ret;
|
||||||
@ -626,6 +653,9 @@ int latin_solver_diff_set(struct latin_solver *solver,
|
|||||||
int extreme)
|
int extreme)
|
||||||
{
|
{
|
||||||
int x, y, n, ret, o = solver->o;
|
int x, y, n, ret, o = solver->o;
|
||||||
|
#ifdef STANDALONE_SOLVER
|
||||||
|
char **names = solver->names;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!extreme) {
|
if (!extreme) {
|
||||||
/*
|
/*
|
||||||
@ -658,7 +688,8 @@ int latin_solver_diff_set(struct latin_solver *solver,
|
|||||||
for (n = 1; n <= o; n++) {
|
for (n = 1; n <= o; n++) {
|
||||||
ret = latin_solver_set(solver, scratch, cubepos(0,0,n), o*o, o
|
ret = latin_solver_set(solver, scratch, cubepos(0,0,n), o*o, o
|
||||||
#ifdef STANDALONE_SOLVER
|
#ifdef STANDALONE_SOLVER
|
||||||
, "positional set elimination, number %d", n
|
, "positional set elimination on %s",
|
||||||
|
names[n-1]
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
if (ret != 0) return ret;
|
if (ret != 0) return ret;
|
||||||
@ -685,6 +716,9 @@ static int latin_solver_recurse
|
|||||||
{
|
{
|
||||||
int best, bestcount;
|
int best, bestcount;
|
||||||
int o = solver->o, x, y, n;
|
int o = solver->o, x, y, n;
|
||||||
|
#ifdef STANDALONE_SOLVER
|
||||||
|
char **names = solver->names;
|
||||||
|
#endif
|
||||||
|
|
||||||
best = -1;
|
best = -1;
|
||||||
bestcount = o+1;
|
bestcount = o+1;
|
||||||
@ -745,7 +779,7 @@ static int latin_solver_recurse
|
|||||||
printf("%*srecursing on (%d,%d) [",
|
printf("%*srecursing on (%d,%d) [",
|
||||||
solver_recurse_depth*4, "", x+1, y+1);
|
solver_recurse_depth*4, "", x+1, y+1);
|
||||||
for (i = 0; i < j; i++) {
|
for (i = 0; i < j; i++) {
|
||||||
printf("%s%d", sep, list[i]);
|
printf("%s%s", sep, names[list[i]-1]);
|
||||||
sep = " or ";
|
sep = " or ";
|
||||||
}
|
}
|
||||||
printf("]\n");
|
printf("]\n");
|
||||||
@ -759,14 +793,15 @@ static int latin_solver_recurse
|
|||||||
for (i = 0; i < j; i++) {
|
for (i = 0; i < j; i++) {
|
||||||
int ret;
|
int ret;
|
||||||
void *newctx;
|
void *newctx;
|
||||||
|
struct latin_solver subsolver;
|
||||||
|
|
||||||
memcpy(outgrid, ingrid, o*o);
|
memcpy(outgrid, ingrid, o*o);
|
||||||
outgrid[y*o+x] = list[i];
|
outgrid[y*o+x] = list[i];
|
||||||
|
|
||||||
#ifdef STANDALONE_SOLVER
|
#ifdef STANDALONE_SOLVER
|
||||||
if (solver_show_working)
|
if (solver_show_working)
|
||||||
printf("%*sguessing %d at (%d,%d)\n",
|
printf("%*sguessing %s at (%d,%d)\n",
|
||||||
solver_recurse_depth*4, "", list[i], x+1, y+1);
|
solver_recurse_depth*4, "", names[list[i]-1], x+1, y+1);
|
||||||
solver_recurse_depth++;
|
solver_recurse_depth++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -775,18 +810,23 @@ static int latin_solver_recurse
|
|||||||
} else {
|
} else {
|
||||||
newctx = ctx;
|
newctx = ctx;
|
||||||
}
|
}
|
||||||
ret = latin_solver(outgrid, o, diff_recursive,
|
latin_solver_alloc(&subsolver, outgrid, o);
|
||||||
diff_simple, diff_set_0, diff_set_1,
|
#ifdef STANDALONE_SOLVER
|
||||||
diff_forcing, diff_recursive,
|
subsolver.names = solver->names;
|
||||||
usersolvers, newctx, ctxnew, ctxfree);
|
#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)
|
if (ctxnew)
|
||||||
ctxfree(newctx);
|
ctxfree(newctx);
|
||||||
|
|
||||||
#ifdef STANDALONE_SOLVER
|
#ifdef STANDALONE_SOLVER
|
||||||
solver_recurse_depth--;
|
solver_recurse_depth--;
|
||||||
if (solver_show_working) {
|
if (solver_show_working) {
|
||||||
printf("%*sretracting %d at (%d,%d)\n",
|
printf("%*sretracting %s at (%d,%d)\n",
|
||||||
solver_recurse_depth*4, "", list[i], x+1, y+1);
|
solver_recurse_depth*4, "", names[list[i]-1], x+1, y+1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* we recurse as deep as we can, so we should never find
|
/* we recurse as deep as we can, so we should never find
|
||||||
@ -836,11 +876,11 @@ static int latin_solver_recurse
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int latin_solver_main(struct latin_solver *solver, int maxdiff,
|
static int latin_solver_top(struct latin_solver *solver, int maxdiff,
|
||||||
int diff_simple, int diff_set_0, int diff_set_1,
|
int diff_simple, int diff_set_0, int diff_set_1,
|
||||||
int diff_forcing, int diff_recursive,
|
int diff_forcing, int diff_recursive,
|
||||||
usersolver_t const *usersolvers, void *ctx,
|
usersolver_t const *usersolvers, void *ctx,
|
||||||
ctxnew_t ctxnew, ctxfree_t ctxfree)
|
ctxnew_t ctxnew, ctxfree_t ctxfree)
|
||||||
{
|
{
|
||||||
struct latin_solver_scratch *scratch = latin_solver_new_scratch(solver);
|
struct latin_solver_scratch *scratch = latin_solver_new_scratch(solver);
|
||||||
int ret, diff = diff_simple;
|
int ret, diff = diff_simple;
|
||||||
@ -938,6 +978,48 @@ int latin_solver_main(struct latin_solver *solver, int maxdiff,
|
|||||||
return diff;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
int latin_solver(digit *grid, int o, int maxdiff,
|
int latin_solver(digit *grid, int o, int maxdiff,
|
||||||
int diff_simple, int diff_set_0, int diff_set_1,
|
int diff_simple, int diff_set_0, int diff_set_1,
|
||||||
int diff_forcing, int diff_recursive,
|
int diff_forcing, int diff_recursive,
|
||||||
|
4
latin.h
4
latin.h
@ -19,6 +19,10 @@ struct latin_solver {
|
|||||||
|
|
||||||
unsigned char *row; /* o^2: row[y*cr+n-1] TRUE if n is in row y */
|
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 */
|
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 cubepos(x,y,n) (((x)*solver->o+(y))*solver->o+(n)-1)
|
||||||
#define cube(x,y,n) (solver->cube[cubepos(x,y,n)])
|
#define cube(x,y,n) (solver->cube[cubepos(x,y,n)])
|
||||||
|
Reference in New Issue
Block a user