Add simple contradiction-driven search mechanism
Gets an about 6% improvement
This commit is contained in:
parent
6e9a6810b3
commit
168cdd8e8e
76
main.c
76
main.c
@ -104,6 +104,70 @@ static update_res_t update(state_t *state, int *x_out, int *y_out)
|
||||
return FOUND_NOTHING;
|
||||
}
|
||||
|
||||
static update_res_t
|
||||
search_at(state_t *state, int x, int y, int *x_out, int *y_out)
|
||||
{
|
||||
update_res_t res;
|
||||
|
||||
state_t with_mine;
|
||||
memcpy(&with_mine, state, sizeof(state_t));
|
||||
with_mine.field[x][y] = MINE;
|
||||
do {
|
||||
int res_x, res_y;
|
||||
switch (res = update(&with_mine, &res_x, &res_y)) {
|
||||
case FOUND_MINE:
|
||||
break;
|
||||
case FOUND_SAFE:
|
||||
with_mine.field[res_x][res_y] = SAFE;
|
||||
break;
|
||||
case FOUND_NOTHING:
|
||||
break;
|
||||
case FOUND_CONTRADICTION:
|
||||
*x_out = x;
|
||||
*y_out = y;
|
||||
return FOUND_SAFE;
|
||||
}
|
||||
} while (res == FOUND_MINE);
|
||||
|
||||
state_t with_safe;
|
||||
memcpy(&with_safe, state, sizeof(state_t));
|
||||
with_safe.field[x][y] = SAFE;
|
||||
do {
|
||||
int res_x, res_y;
|
||||
switch (res = update(&with_safe, &res_x, &res_y)) {
|
||||
case FOUND_MINE:
|
||||
break;
|
||||
case FOUND_SAFE:
|
||||
with_safe.field[res_x][res_y] = SAFE;
|
||||
break;
|
||||
case FOUND_NOTHING:
|
||||
break;
|
||||
case FOUND_CONTRADICTION:
|
||||
state->field[x][y] = MINE;
|
||||
return FOUND_MINE;
|
||||
}
|
||||
} while (res == FOUND_MINE);
|
||||
|
||||
return FOUND_NOTHING;
|
||||
}
|
||||
|
||||
static update_res_t search(state_t *state, int *x_out, int *y_out)
|
||||
{
|
||||
for (int y = 0; y < HEIGHT; ++y) {
|
||||
for (int x = 0; x < WIDTH; ++x) {
|
||||
if (state->field[x][y] != UNKNOWN)
|
||||
continue;
|
||||
|
||||
if (countadj(state->field, x, y, UNKNOWN) != MAX_ADJ) {
|
||||
update_res_t res = search_at(state, x, y, x_out, y_out);
|
||||
if (res == FOUND_MINE || res == FOUND_SAFE)
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FOUND_NOTHING;
|
||||
}
|
||||
|
||||
static status_t solve(int *turns_out)
|
||||
{
|
||||
state_t state = { .mines = 0, .unknown = WIDTH * HEIGHT };
|
||||
@ -123,7 +187,8 @@ static status_t solve(int *turns_out)
|
||||
update_res_t res;
|
||||
do {
|
||||
res = update(&state, &x, &y);
|
||||
assert(res != FOUND_CONTRADICTION);
|
||||
if (res == FOUND_NOTHING)
|
||||
res = search(&state, &x, &y);
|
||||
} while (res == FOUND_MINE);
|
||||
|
||||
if (check(state.field) != OK) {
|
||||
@ -169,12 +234,17 @@ int main(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (nincorrect > 0) {
|
||||
printf(
|
||||
"Fail: %d incorrect! (%0.1f%%)\n", nincorrect,
|
||||
(double)nincorrect / NRUNS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const double solved_prop = (double)nsolved / NRUNS;
|
||||
const double incorrect_prop = (double)nincorrect / NRUNS;
|
||||
const double first_prop = (double)nfirst / NRUNS;
|
||||
const double solved_safe_start_prop = (double)nsolved / (NRUNS - nfirst);
|
||||
printf("Solved %d (%0.1f%%)\n", nsolved, 100 * solved_prop);
|
||||
printf("%d incorrect (%0.1f%%)\n", nincorrect, 100 * incorrect_prop);
|
||||
printf("%d died on first turn (%0.1f%%)\n", nfirst, 100 * first_prop);
|
||||
printf("%0.1f%% solved on safe start\n", 100 * solved_safe_start_prop);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user