From 049fa3405a39abb0eb68bbed056ca497a498e890 Mon Sep 17 00:00:00 2001 From: Nyeogmi Date: Sat, 25 May 2024 16:13:29 -0700 Subject: [PATCH] Whoops, this file didn't get comments --- solver/puzzle.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/solver/puzzle.c b/solver/puzzle.c index 02735e7..1014d96 100644 --- a/solver/puzzle.c +++ b/solver/puzzle.c @@ -32,7 +32,7 @@ void puzzle_undo_propagate_constraints( ); // Return true if cell is bound to something other than '.'. -bool puzzle_is_complete(puzzle_t* puzzle, uint8_t cell); +bool puzzle_cell_is_complete(puzzle_t* puzzle, uint8_t cell); // Bind cell to some value, including '.' void puzzle_set_cell(puzzle_t* puzzle, uint8_t cell, tile_t tile); @@ -75,11 +75,12 @@ void puzzle_solve(puzzle_t* puzzle) { bool puzzle_solve1(puzzle_t* puzzle) { // find best cell to start from + // (which is the cell with the fewest options) uint8_t best_cell_noptions = 255; uint8_t best_cell = 255; for (uint8_t cell = 0; cell < N_CELLS; cell++) { - if (puzzle_is_complete(puzzle, cell)) { + if (puzzle_cell_is_complete(puzzle, cell)) { continue; } puzzle_options_t *options = &puzzle->options[cell]; @@ -91,10 +92,13 @@ bool puzzle_solve1(puzzle_t* puzzle) { } if (best_cell == 255) { - return true; // solved! + // no valid starting cell: continue! + return true; } { + // try every option that's still available (those from 1-9) that appear + // in the options set that we have uint8_t cell = best_cell; puzzle_options_t *options = &puzzle->options[cell]; for (char digit = '1'; digit <= (char) '9'; digit++) { @@ -107,6 +111,9 @@ bool puzzle_solve1(puzzle_t* puzzle) { puzzle_propagate_constraints(puzzle, cell, tile, &result); if (result.viable) { + // puzzle_propagate_constraints may have created a situation + // where there is no need to even try the next branch, as it is + // known to be unsolvable puzzle_set_cell(puzzle, cell, tile); if (puzzle_solve1(puzzle)) { return true; @@ -116,6 +123,7 @@ bool puzzle_solve1(puzzle_t* puzzle) { puzzle_undo_propagate_constraints(puzzle, tile, &result); } + // we didn't explicitly clear this earlier, so clear this here puzzle_set_cell(puzzle, cell, tile_new('.')); } @@ -127,13 +135,18 @@ void puzzle_check_solution(puzzle_t* puzzle) { tile_t original = puzzle->input_board[cell]; tile_t solved = puzzle->solved_board[cell]; + // every cell must be populated if (solved.value == '.') { crash("invalid solution (empty cell)"); } + + // new cells must have the same value as the old cell in their position if (original.value != '.' && original.value != solved.value) { crash("invalid solution (changed original cell)"); } + // there must be no cases where the interference graph sees + // two neighbors with the same tile value cellset_t *interference_row = &interference.rows[cell]; for (uint8_t other_i = 0; other_i < interference_row->count; other_i++) { uint8_t other = interference_row->cells[other_i]; @@ -153,10 +166,13 @@ void puzzle_propagate_constraints( cellset_init(&result->cells); result->viable = true; + // find every row that cell interferes with + // for every incomplete cell in that row, remove this tile value + // from the options cellset_t *interference_row = &interference.rows[cell]; for (uint8_t other_i = 0; other_i < interference_row->count; other_i++) { uint8_t other = interference_row->cells[other_i]; - if (puzzle_is_complete(puzzle, other)) { + if (puzzle_cell_is_complete(puzzle, other)) { continue; } @@ -164,6 +180,7 @@ void puzzle_propagate_constraints( if (puzzle_options_remove(options, tile)) { cellset_add(&result->cells, other); + // if there is no possible value for a cell, then we picked wrong if (puzzle_options_is_empty(options)) { result->viable = false; break; @@ -177,6 +194,7 @@ void puzzle_undo_propagate_constraints( tile_t tile, puzzle_propagate_result_t* result ) { + // we recorded every cell that was touched, so untouch those cells cellset_t *cells = &result->cells; for (uint8_t cell_i = 0; cell_i < cells->count; cell_i++) { uint8_t cell = cells->cells[cell_i]; @@ -184,7 +202,7 @@ void puzzle_undo_propagate_constraints( } } -bool puzzle_is_complete(puzzle_t* puzzle, uint8_t cell) { +bool puzzle_cell_is_complete(puzzle_t* puzzle, uint8_t cell) { return puzzle->solved_board[cell].value != '.'; }