Making it faster by using a max_node pool instead of having it malloc each time.

This commit is contained in:
2026-05-07 00:20:55 +03:00
parent 7e215dc877
commit 00396f86fe
+101 -89
View File
@@ -4,7 +4,8 @@
#include <stdio.h>
#include <stdlib.h>
#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;
}