mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 16:05:44 -07:00
Patch from James H to fix the occasional generation of puzzles
harder than requested. [originally from svn r7113]
This commit is contained in:
81
latin.c
81
latin.c
@ -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.
|
||||||
*/
|
*/
|
||||||
|
2
latin.h
2
latin.h
@ -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;
|
||||||
|
16
unequal.c
16
unequal.c
@ -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.
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user