Implement board solver using board reuse
This commit is contained in:
parent
0e4506cd52
commit
10ad1cdf67
96
main.c
96
main.c
@ -7,10 +7,54 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How many boards to allocate by default for board spec
|
||||||
|
* Average depth for highly complex boards is between 10 and 12
|
||||||
|
*/
|
||||||
|
#define DEFAULT_DEPTH 10
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How many boards to allocate per depth increase
|
||||||
|
* Higher values mean fewer reallocations, by with greater resource costs
|
||||||
|
*/
|
||||||
|
#define DEPTH_INCREMENT 3
|
||||||
|
|
||||||
|
|
||||||
|
struct boards_table {
|
||||||
|
struct board **board_specs;
|
||||||
|
unsigned long long max_depth;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
tables_ensure_depth (struct boards_table *board_spec, unsigned long long depth)
|
||||||
|
{
|
||||||
|
if (board_spec->max_depth <= depth)
|
||||||
|
{
|
||||||
|
/* Compute new max depth */
|
||||||
|
unsigned long long new_max;
|
||||||
|
if (board_spec->max_depth == 0)
|
||||||
|
new_max = DEFAULT_DEPTH;
|
||||||
|
else
|
||||||
|
new_max = board_spec->max_depth + DEPTH_INCREMENT;
|
||||||
|
|
||||||
|
/* Disregard NULL return value. What's it gonna do, segfault? :P */
|
||||||
|
board_spec->board_specs = realloc (
|
||||||
|
board_spec->board_specs,
|
||||||
|
sizeof (struct board *) * new_max
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Allocate boards */
|
||||||
|
for (unsigned long long l = board_spec->max_depth; l < new_max; ++l)
|
||||||
|
board_spec->board_specs[l] = malloc (sizeof (struct board));
|
||||||
|
|
||||||
|
/* Update max depth */
|
||||||
|
board_spec->max_depth = new_max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
simplify (struct board *board, unsigned long long depth);
|
simplify (struct boards_table *board_spec, unsigned long long depth);
|
||||||
|
|
||||||
|
|
||||||
struct board_file
|
struct board_file
|
||||||
@ -176,8 +220,11 @@ first_potential_value (struct board_element *element, struct board *board, bool
|
|||||||
* Reduce away all elements on board with complexity=1 until none remain
|
* Reduce away all elements on board with complexity=1 until none remain
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
simplify (struct board *board, unsigned long long depth)
|
simplify (struct boards_table *board_specs, unsigned long long depth)
|
||||||
{
|
{
|
||||||
|
/* Get current table */
|
||||||
|
struct board *board = board_specs->board_specs[depth];
|
||||||
|
|
||||||
bool error;
|
bool error;
|
||||||
/* Reduce using low-complexity computation */
|
/* Reduce using low-complexity computation */
|
||||||
while (board->complexity == 1)
|
while (board->complexity == 1)
|
||||||
@ -212,31 +259,30 @@ simplify (struct board *board, unsigned long long depth)
|
|||||||
for (element_value value = 0; value < 9; ++value)
|
for (element_value value = 0; value < 9; ++value)
|
||||||
{
|
{
|
||||||
/* Try speculative placement of each potential value and recurse */
|
/* Try speculative placement of each potential value and recurse */
|
||||||
|
tables_ensure_depth (board_specs, depth + 1);
|
||||||
if ((elem->potential & (1 << value)) != 0)
|
if ((elem->potential & (1 << value)) != 0)
|
||||||
{
|
{
|
||||||
/* printf ("Speculating (%u, %u) = %u (depth = %llu)\n", x, y, value, depth); */
|
|
||||||
struct board *board_spec =
|
struct board *board_spec =
|
||||||
board_place_speculative (board, x, y, value);
|
board_place_speculative (
|
||||||
|
board,
|
||||||
|
board_specs->board_specs[depth + 1],
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
value
|
||||||
|
);
|
||||||
|
|
||||||
/* If speculative placement failed, try another value */
|
/* If speculative placement failed, try another value */
|
||||||
if (board_spec == NULL)
|
if (board_spec == NULL)
|
||||||
{
|
|
||||||
/* printf ("Speculation failed catastrophically\n"); */
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
/* Found solution */
|
/* Found solution */
|
||||||
if (simplify (board_spec, depth + 1) && board_spec->complexity == 0)
|
if (simplify (board_specs, depth + 1) && board_spec->complexity == 0)
|
||||||
{
|
{
|
||||||
board_copy (board_spec, board);
|
board_copy (board_spec, board);
|
||||||
x = 9;
|
x = 9;
|
||||||
y = 9;
|
y = 9;
|
||||||
value = 9;
|
value = 9;
|
||||||
}
|
}
|
||||||
/* else printf ("Speculation failed\n"); */
|
|
||||||
|
|
||||||
/* board_copy leaves resposibility of freeing to caller */
|
|
||||||
free (board_spec);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -254,27 +300,33 @@ main (int argc, char **argv, char **env)
|
|||||||
if (file.fd == -1 || file.data == NULL)
|
if (file.fd == -1 || file.data == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
struct board board;
|
/* Allocate board */
|
||||||
copy_to_board (file, &board);
|
struct boards_table boards;
|
||||||
|
boards.max_depth = 0;
|
||||||
|
tables_ensure_depth (&boards, 0);
|
||||||
|
|
||||||
|
struct board *root_board = boards.board_specs[0];
|
||||||
|
|
||||||
|
copy_to_board (file, root_board);
|
||||||
|
|
||||||
close_board_file (file);
|
close_board_file (file);
|
||||||
|
|
||||||
board_update_all_marks (&board);
|
board_update_all_marks (root_board);
|
||||||
|
|
||||||
print_board (&board);
|
print_board (root_board);
|
||||||
|
|
||||||
if (board_is_valid (&board))
|
if (board_is_valid (root_board))
|
||||||
printf ("Board is valid!\nBoard complexity: %u\n", board.complexity);
|
printf ("Board is valid!\nBoard complexity: %u\n", root_board->complexity);
|
||||||
else
|
else
|
||||||
puts ("Board is invalid!");
|
puts ("Board is invalid!");
|
||||||
|
|
||||||
puts("\nReducing...");
|
puts("\nReducing...");
|
||||||
simplify (&board, 1);
|
simplify (&boards, 0);
|
||||||
|
|
||||||
print_board (&board);
|
print_board (root_board);
|
||||||
|
|
||||||
if (board_is_valid (&board))
|
if (board_is_valid (root_board))
|
||||||
printf ("Board is valid!\nBoard complexity: %u\n", board.complexity);
|
printf ("Board is valid!\nBoard complexity: %u\n", root_board->complexity);
|
||||||
else
|
else
|
||||||
puts ("Board is invalid!");
|
puts ("Board is invalid!");
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user