mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 08:01:30 -07:00
Run the final solution-reduction pass in both directions, since
Gareth managed to find an example (10x8#458168771440033 in r6289) where running it in only one direction failed to eliminate an obviously redundant piece of path. [originally from svn r6290] [r6289 == b25fcc3f2621b0b41f3ae7cdabe57ed07f62d2c2]
This commit is contained in:
82
inertia.c
82
inertia.c
@ -1160,7 +1160,7 @@ static char *solve_game(game_state *state, game_state *currstate,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TSP_DIAGNOSTICS
|
||||
#ifndef TSP_DIAGNOSTICS
|
||||
printf("before reduction, moves are ");
|
||||
x = nodes[circuit[0]] / DP1 % w;
|
||||
y = nodes[circuit[0]] / DP1 / w;
|
||||
@ -1198,6 +1198,9 @@ static char *solve_game(game_state *state, game_state *currstate,
|
||||
*/
|
||||
while (1) {
|
||||
int oldlen = circuitlen;
|
||||
int dir;
|
||||
|
||||
for (dir = +1; dir >= -1; dir -= 2) {
|
||||
|
||||
for (i = 0; i < wh; i++)
|
||||
unvisited[i] = 0;
|
||||
@ -1220,31 +1223,41 @@ static char *solve_game(game_state *state, game_state *currstate,
|
||||
if (i < wh)
|
||||
break;
|
||||
|
||||
for (i = j = 0; i < circuitlen; i++) {
|
||||
for (i = j = (dir > 0 ? 0 : circuitlen-1);
|
||||
i < circuitlen && i >= 0;
|
||||
i += dir) {
|
||||
int xy = nodes[circuit[i]] / DP1;
|
||||
if (currstate->grid[xy] == GEM && unvisited[xy] > 1) {
|
||||
unvisited[xy]--;
|
||||
} else if (currstate->grid[xy] == GEM || i == circuitlen-1) {
|
||||
/*
|
||||
* circuit[i] collects a gem for the only time, or is
|
||||
* the last node in the circuit. Therefore it cannot be
|
||||
* removed; so we now want to replace the path from
|
||||
* circuit[j] to circuit[i] with a bfs-shortest path.
|
||||
* circuit[i] collects a gem for the only time,
|
||||
* or is the last node in the circuit.
|
||||
* Therefore it cannot be removed; so we now
|
||||
* want to replace the path from circuit[j] to
|
||||
* circuit[i] with a bfs-shortest path.
|
||||
*/
|
||||
int k, dest, ni, ti, thisdist;
|
||||
int p, q, k, dest, ni, ti, thisdist;
|
||||
|
||||
#ifdef TSP_DIAGNOSTICS
|
||||
printf("optimising section from %d - %d\n", j, i);
|
||||
/*
|
||||
* Set up the upper and lower bounds of the
|
||||
* reduced section.
|
||||
*/
|
||||
p = min(i, j);
|
||||
q = max(i, j);
|
||||
|
||||
#ifndef TSP_DIAGNOSTICS
|
||||
printf("optimising section from %d - %d\n", p, q);
|
||||
#endif
|
||||
|
||||
for (k = 0; k < n; k++)
|
||||
dist[k] = -1;
|
||||
head = tail = 0;
|
||||
|
||||
dist[circuit[j]] = 0;
|
||||
list[tail++] = circuit[j];
|
||||
dist[circuit[p]] = 0;
|
||||
list[tail++] = circuit[p];
|
||||
|
||||
while (head < tail && dist[circuit[i]] < 0) {
|
||||
while (head < tail && dist[circuit[q]] < 0) {
|
||||
int ni = list[head++];
|
||||
for (k = edgei[ni]; k < edgei[ni+1]; k++) {
|
||||
int ti = edges[k];
|
||||
@ -1255,22 +1268,25 @@ static char *solve_game(game_state *state, game_state *currstate,
|
||||
}
|
||||
}
|
||||
|
||||
thisdist = dist[circuit[i]];
|
||||
assert(thisdist >= 0 && thisdist <= i-j);
|
||||
thisdist = dist[circuit[q]];
|
||||
assert(thisdist >= 0 && thisdist <= q-p);
|
||||
|
||||
memmove(circuit+j+thisdist, circuit+i,
|
||||
(circuitlen - i) * sizeof(int));
|
||||
circuitlen -= i-j;
|
||||
i = j + thisdist;
|
||||
circuitlen += i-j;
|
||||
memmove(circuit+p+thisdist, circuit+q,
|
||||
(circuitlen - q) * sizeof(int));
|
||||
circuitlen -= q-p;
|
||||
q = p + thisdist;
|
||||
circuitlen += q-p;
|
||||
|
||||
#ifdef TSP_DIAGNOSTICS
|
||||
printf("new section runs from %d - %d\n", j, i);
|
||||
if (dir > 0)
|
||||
i = q; /* resume loop from the right place */
|
||||
|
||||
#ifndef TSP_DIAGNOSTICS
|
||||
printf("new section runs from %d - %d\n", p, q);
|
||||
#endif
|
||||
|
||||
dest = i;
|
||||
dest = q;
|
||||
assert(dest >= 0);
|
||||
ni = circuit[i];
|
||||
ni = circuit[q];
|
||||
|
||||
while (1) {
|
||||
/* printf("dest=%d circuitlen=%d ni=%d dist[ni]=%d\n", dest, circuitlen, ni, dist[ni]); */
|
||||
@ -1289,16 +1305,18 @@ static char *solve_game(game_state *state, game_state *currstate,
|
||||
}
|
||||
|
||||
/*
|
||||
* Now re-increment the visit counts for the new
|
||||
* path.
|
||||
* Now re-increment the visit counts for the
|
||||
* new path.
|
||||
*/
|
||||
while (++j < i) {
|
||||
int xy = nodes[circuit[j]] / DP1;
|
||||
while (++p < q) {
|
||||
int xy = nodes[circuit[p]] / DP1;
|
||||
if (currstate->grid[xy] == GEM)
|
||||
unvisited[xy]++;
|
||||
}
|
||||
|
||||
#ifdef TSP_DIAGNOSTICS
|
||||
j = i;
|
||||
|
||||
#ifndef TSP_DIAGNOSTICS
|
||||
printf("during reduction, circuit is");
|
||||
for (k = 0; k < circuitlen; k++) {
|
||||
int nc = nodes[circuit[k]];
|
||||
@ -1327,7 +1345,7 @@ static char *solve_game(game_state *state, game_state *currstate,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TSP_DIAGNOSTICS
|
||||
#ifndef TSP_DIAGNOSTICS
|
||||
printf("after reduction, moves are ");
|
||||
x = nodes[circuit[0]] / DP1 % w;
|
||||
y = nodes[circuit[0]] / DP1 / w;
|
||||
@ -1347,10 +1365,12 @@ static char *solve_game(game_state *state, game_state *currstate,
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* If we've managed an entire reduction pass and not made
|
||||
* the solution any shorter, we're _really_ done.
|
||||
* If we've managed an entire reduction pass in each
|
||||
* direction and not made the solution any shorter, we're
|
||||
* _really_ done.
|
||||
*/
|
||||
if (circuitlen == oldlen)
|
||||
break;
|
||||
|
Reference in New Issue
Block a user