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 <stdio.h>
|
||||||
#include <stdlib.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;
|
int128_t LIMIT = 0;
|
||||||
|
|
||||||
typedef struct GlobalEntry {
|
typedef struct GlobalEntry {
|
||||||
@@ -78,41 +79,48 @@ typedef struct VisEntry {
|
|||||||
struct VisEntry* next;
|
struct VisEntry* next;
|
||||||
} VisEntry;
|
} 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};
|
static VisEntry* hash_table[HASH_SIZE] = {0};
|
||||||
|
|
||||||
|
// O(1) Clear: Just reset the pointers and null the hash table
|
||||||
void clear_hash_table() {
|
void clear_hash_table() {
|
||||||
for (size_t i = 0; i < HASH_SIZE; ++i) {
|
vis_ptr = 0;
|
||||||
VisEntry* cur = hash_table[i];
|
for (size_t i = 0; i < HASH_SIZE; ++i) hash_table[i] = NULL;
|
||||||
while (cur) {
|
|
||||||
VisEntry* nx = cur->next;
|
|
||||||
free(cur);
|
|
||||||
cur = nx;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
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);
|
unsigned int h = hash_three128(a,b,c);
|
||||||
VisEntry* cur = hash_table[h];
|
VisEntry* cur = hash_table[h];
|
||||||
while (cur) {
|
while (cur) {
|
||||||
if (cur->a == a && cur->b == b && cur->c == c) return 0;
|
if (cur->a == a && cur->b == b && cur->c == c) return 0;
|
||||||
cur = cur->next;
|
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->a = a; e->b = b; e->c = c;
|
||||||
e->next = hash_table[h];
|
e->next = hash_table[h];
|
||||||
hash_table[h] = e;
|
hash_table[h] = e;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Node* q_front = NULL;
|
|
||||||
static Node* q_back = NULL;
|
|
||||||
|
|
||||||
static void enqueue(Node* n) {
|
static void enqueue(Node* n) {
|
||||||
n->next = NULL;
|
n->next = NULL;
|
||||||
@@ -132,11 +140,6 @@ static Node* dequeue() {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void drain_queue() {
|
|
||||||
Node* n;
|
|
||||||
while ((n = dequeue()) != NULL) free(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int safe_val(int128_t x) {
|
static int safe_val(int128_t x) {
|
||||||
if (x > LIMIT || x < -LIMIT) return 0;
|
if (x > LIMIT || x < -LIMIT) return 0;
|
||||||
return 1;
|
return 1;
|
||||||
@@ -157,8 +160,8 @@ static void make_move(char move, Node* curr) {
|
|||||||
// Validation and Enqueue
|
// Validation and Enqueue
|
||||||
if (safe_val(na) && safe_val(nb) && safe_val(nc)) {
|
if (safe_val(na) && safe_val(nb) && safe_val(nc)) {
|
||||||
if (visit_and_mark(na, nb, nc)) {
|
if (visit_and_mark(na, nb, nc)) {
|
||||||
Node* n = (Node*)malloc(sizeof(Node));
|
if (node_ptr >= MAX_NODES) return; // Pool safety
|
||||||
if (!n) { fprintf(stderr, "Out of memory\n"); exit(1); }
|
Node* n = &node_pool[node_ptr++];
|
||||||
n->a = na; n->b = nb; n->c = nc;
|
n->a = na; n->b = nb; n->c = nc;
|
||||||
n->move = move;
|
n->move = move;
|
||||||
n->parent = curr;
|
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() {
|
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;
|
int mode = 0, print_mode = 0;
|
||||||
int128_t a0 = 10, b0 = 6, c0 = 0, sum = 0;
|
int128_t a0 = 10, b0 = 6, c0 = 0, sum = 0;
|
||||||
while (mode == 0) {
|
while (mode == 0) {
|
||||||
@@ -260,69 +337,4 @@ int main() {
|
|||||||
print_int128(sum); printf("\n");
|
print_int128(sum); printf("\n");
|
||||||
}
|
}
|
||||||
return 0;
|
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