Patch from James H to fix the occasional generation of puzzles

harder than requested.

[originally from svn r7113]
This commit is contained in:
Simon Tatham
2007-01-15 20:07:18 +00:00
parent 7a41702606
commit 472deca37c
3 changed files with 59 additions and 40 deletions

81
latin.c
View File

@ -619,46 +619,46 @@ int latin_solver_diff_simple(struct latin_solver *solver)
int latin_solver_diff_set(struct latin_solver *solver, int latin_solver_diff_set(struct latin_solver *solver,
struct latin_solver_scratch *scratch, struct latin_solver_scratch *scratch,
int *extreme) int extreme)
{ {
int x, y, n, ret, o = solver->o; int x, y, n, ret, o = solver->o;
/*
* Row-wise set elimination.
*/
for (y = 0; y < o; y++) {
ret = latin_solver_set(solver, scratch, cubepos(0,y,1), o*o, 1
#ifdef STANDALONE_SOLVER
, "set elimination, row %d", YUNTRANS(y)
#endif
);
if (ret > 0) *extreme = 0;
if (ret != 0) return ret;
}
/* if (!extreme) {
* Column-wise set elimination. /*
*/ * Row-wise set elimination.
for (x = 0; x < o; x++) { */
ret = latin_solver_set(solver, scratch, cubepos(x,0,1), o, 1 for (y = 0; y < o; y++) {
ret = latin_solver_set(solver, scratch, cubepos(0,y,1), o*o, 1
#ifdef STANDALONE_SOLVER #ifdef STANDALONE_SOLVER
, "set elimination, column %d", x , "set elimination, row %d", YUNTRANS(y)
#endif #endif
); );
if (ret > 0) *extreme = 0; if (ret != 0) return ret;
if (ret != 0) return ret; }
} /*
* Column-wise set elimination.
/* */
* Row-vs-column set elimination on a single number. for (x = 0; x < o; x++) {
*/ ret = latin_solver_set(solver, scratch, cubepos(x,0,1), o, 1
for (n = 1; n <= o; n++) {
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 , "set elimination, column %d", x
#endif #endif
); );
if (ret > 0) *extreme = 1; if (ret != 0) return ret;
if (ret != 0) return ret; }
} else {
/*
* Row-vs-column set elimination on a single number
* (much tricker for a human to do!)
*/
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
#endif
);
if (ret != 0) return ret;
}
} }
return 0; return 0;
} }
@ -826,7 +826,7 @@ enum { diff_simple = 1, diff_set, diff_extreme, diff_recursive };
static int latin_solver_sub(struct latin_solver *solver, int maxdiff, void *ctx) static int latin_solver_sub(struct latin_solver *solver, int maxdiff, void *ctx)
{ {
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, extreme; int ret, diff = diff_simple;
assert(maxdiff <= diff_recursive); assert(maxdiff <= diff_recursive);
/* /*
@ -859,18 +859,27 @@ static int latin_solver_sub(struct latin_solver *solver, int maxdiff, void *ctx)
if (maxdiff <= diff_simple) if (maxdiff <= diff_simple)
break; break;
ret = latin_solver_diff_set(solver, scratch, &extreme); ret = latin_solver_diff_set(solver, scratch, 0);
if (ret < 0) { if (ret < 0) {
diff = diff_impossible; diff = diff_impossible;
goto got_result; goto got_result;
} else if (ret > 0) { } else if (ret > 0) {
diff = max(diff, extreme ? diff_extreme : diff_set); diff = max(diff, diff_set);
goto cont; goto cont;
} }
if (maxdiff <= diff_set) if (maxdiff <= diff_set)
break; break;
ret = latin_solver_diff_set(solver, scratch, 1);
if (ret < 0) {
diff = diff_impossible;
goto got_result;
} else if (ret > 0) {
diff = max(diff, diff_extreme);
goto cont;
}
/* /*
* Forcing chains. * Forcing chains.
*/ */

View File

@ -86,7 +86,7 @@ int latin_solver_diff_simple(struct latin_solver *solver);
* the more difficult single-number elimination. */ * the more difficult single-number elimination. */
int latin_solver_diff_set(struct latin_solver *solver, int latin_solver_diff_set(struct latin_solver *solver,
struct latin_solver_scratch *scratch, struct latin_solver_scratch *scratch,
int *extreme); int extreme);
typedef int (latin_solver_callback)(digit *, int, int, void*); typedef int (latin_solver_callback)(digit *, int, int, void*);
/* Use to provide a standard way of dealing with solvers which can recurse; /* Use to provide a standard way of dealing with solvers which can recurse;

View File

@ -631,7 +631,7 @@ static int solver_grid(digit *grid, int o, int maxdiff, void *ctx)
game_solver *solver; game_solver *solver;
struct latin_solver *lsolver; struct latin_solver *lsolver;
struct latin_solver_scratch *scratch; struct latin_solver_scratch *scratch;
int ret, diff = DIFF_LATIN, extreme; int ret, diff = DIFF_LATIN;
assert(maxdiff <= DIFF_RECURSIVE); assert(maxdiff <= DIFF_RECURSIVE);
@ -668,18 +668,28 @@ cont:
if (maxdiff <= DIFF_EASY) if (maxdiff <= DIFF_EASY)
break; break;
ret = latin_solver_diff_set(lsolver, scratch, &extreme); /* Row- and column-wise set elimination */
ret = latin_solver_diff_set(lsolver, scratch, 0);
if (ret < 0) { if (ret < 0) {
diff = DIFF_IMPOSSIBLE; diff = DIFF_IMPOSSIBLE;
goto got_result; goto got_result;
} else if (ret > 0) { } else if (ret > 0) {
diff = max(diff, extreme ? DIFF_EXTREME : DIFF_SET); diff = max(diff, DIFF_SET);
goto cont; goto cont;
} }
if (maxdiff <= DIFF_SET) if (maxdiff <= DIFF_SET)
break; break;
ret = latin_solver_diff_set(lsolver, scratch, 1);
if (ret < 0) {
diff = DIFF_IMPOSSIBLE;
goto got_result;
} else if (ret > 0) {
diff = max(diff, DIFF_EXTREME);
goto cont;
}
/* /*
* Forcing chains. * Forcing chains.
*/ */