Making it faster by using a max_node pool instead of having it malloc each time.
This commit is contained in:
+101
-89
@@ -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) {
|
||||
@@ -261,68 +338,3 @@ int main() {
|
||||
}
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user