diff --git a/chess_paths/chess_paths.c b/chess_paths/chess_paths.c index 174c70c..e19457d 100644 --- a/chess_paths/chess_paths.c +++ b/chess_paths/chess_paths.c @@ -255,20 +255,79 @@ unsigned int decreasing_path_len(const struct chessboard* c, return hops - 1; } -void visit(bool* visited, unsigned columns, unsigned column, unsigned row) { - visited[column * columns + row] = true; +struct row_list { + unsigned row; + unsigned column; + struct row_list* next; +}; + +typedef struct row_list* visit_table; +unsigned long alloc = 0; + +unsigned long table_total_size(const struct chessboard*); +unsigned long table_hash(const struct chessboard*, unsigned, unsigned); + +inline unsigned long table_total_size(const struct chessboard* c) { + return 100; } -bool visited(bool* visited, unsigned columns, unsigned column, unsigned row) { - return visited[column * columns + row]; +inline unsigned long table_hash(const struct chessboard* c, unsigned col, + unsigned row) { + return (value_at(c, col, row) ^ 0xDEADBEEF) % table_total_size(c); +} + +visit_table* table_new(const struct chessboard* c) { + unsigned long table_size = table_total_size(c); + alloc += sizeof(struct row_list*) * table_size; + return calloc(table_size, sizeof(struct row_list*)); +} + +void table_visit(const struct chessboard* c, visit_table* visited, + unsigned column, unsigned row) { + + unsigned long hash = table_hash(c, column, row); + struct row_list* prev = hash[visited]; + alloc += sizeof(struct row_list); + hash[visited] = malloc(sizeof(struct row_list)); + assert(hash[visited] != NULL); + hash[visited]->row = row; + hash[visited]->column = column; + hash[visited]->next = prev; +} + +bool table_visited(const struct chessboard* c, visit_table* visited, + unsigned column, unsigned row) { + + unsigned long hash = table_hash(c, column, row); + for (struct row_list* i = hash[visited]; i != NULL; i = i->next) { + if (i->row == row && i->column == column) return true; + } + return false; +} + +void table_destroy(const struct chessboard* c, visit_table* visited) { + + unsigned long table_size = table_total_size(c); + for (unsigned e = 0; e < table_size; e++) { + for (struct row_list* i = e[visited], *j; i != NULL;) { + j = i->next; + free(i); + i = j; + } + } + + printf("alloc = %lu\n", alloc); + alloc = 0; + + free(visited); } unsigned int simple_path_len(const struct chessboard* c, struct piece_position* p) { - const unsigned int CC = columns(c); - bool* v = calloc(rows(c) * CC, sizeof(unsigned)); - visit(v, CC, p->column, p->row); + visit_table* v = table_new(c); + table_visit(c, v, p->column, p->row); + #if DEBUG print_visited(c, v); #endif @@ -287,7 +346,7 @@ unsigned int simple_path_len(const struct chessboard* c, #endif while(poss != NULL) { - if (!visited(v, CC, poss->column, poss->row)) { + if (!table_visited(c, v, poss->column, poss->row)) { next_v = value_at(c, poss->column, poss->row); if (!has_next || next_v > base_v) { has_next = true; @@ -301,14 +360,14 @@ unsigned int simple_path_len(const struct chessboard* c, free(del); } - visit(v, CC, p->column, p->row); + table_visit(c, v, p->column, p->row); #if DEBUG print_visited(c, v); #endif hops++; } - free(v); + table_destroy(c, v); return hops - 1; }