From 168cdd8e8e00e66808a584218c5e9fa97bce51d0 Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Sun, 9 Mar 2025 09:53:14 +0000 Subject: [PATCH] Add simple contradiction-driven search mechanism Gets an about 6% improvement --- main.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 3 deletions(-) diff --git a/main.c b/main.c index 9c1bf1a..aca745e 100644 --- a/main.c +++ b/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);