From 00396f86fe1df064fda8d5a7c24de8eb098b7014 Mon Sep 17 00:00:00 2001 From: Georgios Chatzopoulos Date: Thu, 7 May 2026 00:20:55 +0300 Subject: [PATCH] Making it faster by using a max_node pool instead of having it malloc each time. --- src/stergios.c | 190 ++++++++++++++++++++++++++----------------------- 1 file changed, 101 insertions(+), 89 deletions(-) diff --git a/src/stergios.c b/src/stergios.c index e4b90b3..7215928 100755 --- a/src/stergios.c +++ b/src/stergios.c @@ -4,7 +4,8 @@ #include #include -#define HASH_SIZE 200003 +#define HASH_SIZE 2000003 +#define MAX_NODES 40000000 // 40 Million nodes (~4.5GB RAM) int128_t LIMIT = 0; typedef struct GlobalEntry { @@ -78,41 +79,48 @@ typedef struct VisEntry { struct VisEntry* next; } VisEntry; +// Pre-allocated Pools +static Node* node_pool = NULL; +static VisEntry* vis_pool = NULL; +static int node_ptr = 0; +static int vis_ptr = 0; +static Node* q_front = NULL; +static Node* q_back = NULL; + static VisEntry* hash_table[HASH_SIZE] = {0}; +// O(1) Clear: Just reset the pointers and null the hash table void clear_hash_table() { - for (size_t i = 0; i < HASH_SIZE; ++i) { - VisEntry* cur = hash_table[i]; - while (cur) { - VisEntry* nx = cur->next; - free(cur); - cur = nx; - } - - hash_table[i] = NULL; - } + vis_ptr = 0; + for (size_t i = 0; i < HASH_SIZE; ++i) hash_table[i] = NULL; } -int run_bfs(int128_t* sum, int128_t a0, int128_t b0, int128_t c0, int print_mode); - +void drain_queue() { + node_ptr = 0; + q_front = q_back = NULL; +} static int visit_and_mark(int128_t a, int128_t b, int128_t c) { + sort_triplet(&a, &b, &c); unsigned int h = hash_three128(a,b,c); VisEntry* cur = hash_table[h]; while (cur) { if (cur->a == a && cur->b == b && cur->c == c) return 0; cur = cur->next; } - VisEntry* e = (VisEntry*)malloc(sizeof(VisEntry)); - if (!e) { fprintf(stderr, "Out of memory\n"); exit(1); } + + if (vis_ptr >= MAX_NODES) { + fprintf(stderr, "VisPool Overflow! Increase MAX_NODES.\n"); + exit(1); + } + + VisEntry* e = &vis_pool[vis_ptr++]; e->a = a; e->b = b; e->c = c; e->next = hash_table[h]; hash_table[h] = e; return 1; } -static Node* q_front = NULL; -static Node* q_back = NULL; static void enqueue(Node* n) { n->next = NULL; @@ -132,11 +140,6 @@ static Node* dequeue() { return r; } -void drain_queue() { - Node* n; - while ((n = dequeue()) != NULL) free(n); -} - static int safe_val(int128_t x) { if (x > LIMIT || x < -LIMIT) return 0; return 1; @@ -157,8 +160,8 @@ static void make_move(char move, Node* curr) { // Validation and Enqueue if (safe_val(na) && safe_val(nb) && safe_val(nc)) { if (visit_and_mark(na, nb, nc)) { - Node* n = (Node*)malloc(sizeof(Node)); - if (!n) { fprintf(stderr, "Out of memory\n"); exit(1); } + if (node_ptr >= MAX_NODES) return; // Pool safety + Node* n = &node_pool[node_ptr++]; n->a = na; n->b = nb; n->c = nc; n->move = move; n->parent = curr; @@ -200,7 +203,81 @@ static void try_push_children(Node* curr) { } } +int run_bfs(int128_t* sum, int128_t a0, int128_t b0, int128_t c0, int print_mode) { + drain_queue(); + clear_hash_table(); + + if (node_ptr >= MAX_NODES) return 0; + Node* root = &node_pool[node_ptr++]; + root->a = a0; root->b = b0; root->c = c0; + root->move = '\0'; root->parent = NULL; root->next = NULL; + enqueue(root); + visit_and_mark(a0, b0, c0); + + Node* found = NULL; + while ((root = dequeue()) != NULL) { + if (root->a == 0 || root->b == 0 || root->c == 0) { found = root; break; } + try_push_children(root); + } + + if (!found) { + printf("No solution found within bounds/search limits.\n"); + drain_queue(); + clear_hash_table(); + return 0; + } + + int max_moves = 0; + for (Node* p = found; p && p->move != '\0'; p = p->parent) max_moves++; + + char* moves; + if (print_mode == 1) { + moves = malloc(max_moves + 1); + if (!moves) { fprintf(stderr, "Out of memory\n"); return 0; } + moves[max_moves] = '\0'; + + Node* p = found; + int idx = max_moves - 1; + while (p && p->move != '\0') { + moves[idx--] = p->move; + p = p->parent; + } + + printf("\nSolution found!\n"); + printf("Initial: ("); + print_int128(a0); printf(", "); + print_int128(b0); printf(", "); + print_int128(c0); printf(")\n"); + + printf("Final: ("); + print_int128(found->a); printf(", "); + print_int128(found->b); printf(", "); + print_int128(found->c); printf(")\n"); + + printf("Moves (%d): %s\n", max_moves, moves); + } else if (print_mode == 2) { + print_int128(c0); + printf(" the required amount of moves is: %d\n", max_moves); + } + *sum+=max_moves; + + if (print_mode == 1) free(moves); + drain_queue(); + clear_hash_table(); + + return 1; +} + int main() { + // Allocate the giant pools once + node_pool = malloc(sizeof(Node) * MAX_NODES); + vis_pool = malloc(sizeof(VisEntry) * MAX_NODES); + + if (!node_pool || !vis_pool) { + fprintf(stderr, "Failed to allocate memory pools. Try a smaller MAX_NODES.\n"); + return 1; + } + int mode = 0, print_mode = 0; int128_t a0 = 10, b0 = 6, c0 = 0, sum = 0; while (mode == 0) { @@ -260,69 +337,4 @@ int main() { print_int128(sum); printf("\n"); } return 0; -} - -int run_bfs(int128_t* sum, int128_t a0, int128_t b0, int128_t c0, int print_mode) { - drain_queue(); - clear_hash_table(); - - Node* root = malloc(sizeof(Node)); - if (!root) { fprintf(stderr, "Out of memory\n"); return 0; } - root->a = a0; root->b = b0; root->c = c0; - root->move = '\0'; root->parent = NULL; root->next = NULL; - enqueue(root); - visit_and_mark(a0, b0, c0); - - Node* found = NULL; - while ((root = dequeue()) != NULL) { - if (root->a == 0 || root->b == 0 || root->c == 0) { found = root; break; } - try_push_children(root); - } - - if (!found) { - printf("No solution found within bounds/search limits.\n"); - drain_queue(); - clear_hash_table(); - return 0; - } - - int max_moves = 0; - for (Node* p = found; p && p->move != '\0'; p = p->parent) max_moves++; - - char* moves; - if (print_mode == 1) { - moves = malloc(max_moves + 1); - if (!moves) { fprintf(stderr, "Out of memory\n"); return 0; } - moves[max_moves] = '\0'; - - Node* p = found; - int idx = max_moves - 1; - while (p && p->move != '\0') { - moves[idx--] = p->move; - p = p->parent; - } - - printf("\nSolution found!\n"); - printf("Initial: ("); - print_int128(a0); printf(", "); - print_int128(b0); printf(", "); - print_int128(c0); printf(")\n"); - - printf("Final: ("); - print_int128(found->a); printf(", "); - print_int128(found->b); printf(", "); - print_int128(found->c); printf(")\n"); - - printf("Moves (%d): %s\n", max_moves, moves); - } else if (print_mode == 2) { - print_int128(c0); - printf(" the required amount of moves is: %d\n", max_moves); - } - *sum+=max_moves; - - if (print_mode == 1) free(moves); - drain_queue(); - clear_hash_table(); - - return 1; } \ No newline at end of file