123 lines
3.0 KiB
C
123 lines
3.0 KiB
C
#include "node.h"
|
|
#include "hash.h"
|
|
#include "maths.h"
|
|
#include "queue.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
static Node* pool = NULL;
|
|
static VisitedEntry* visited_pool = NULL;
|
|
static VisitedEntry* hash_table[HASH_SIZE] = {0};
|
|
static int pool_ptr = 0;
|
|
static int pool_capacity = 0;
|
|
static int visited_ptr = 0;
|
|
|
|
void node_pool_init(int max_nodes) {
|
|
pool_capacity = max_nodes;
|
|
pool = malloc(pool_capacity * sizeof(Node));
|
|
visited_pool = malloc(pool_capacity * sizeof(VisitedEntry));
|
|
if (!pool || !visited_pool) {
|
|
fprintf(stderr, "Fatal: Could not allocate Node Pool for %d nodes.\n", max_nodes);
|
|
exit(1);
|
|
}
|
|
pool_ptr = 0;
|
|
visited_ptr = 0;
|
|
for (size_t i = 0; i < HASH_SIZE; ++i) hash_table[i] = NULL;
|
|
}
|
|
|
|
Node* node_pool_alloc() {
|
|
if (pool_ptr >= pool_capacity) {
|
|
fprintf(stderr, "\nNode Pool Overflow! Need more than %d nodes.\n", pool_capacity);
|
|
return NULL;
|
|
}
|
|
return &pool[pool_ptr++];
|
|
}
|
|
|
|
void node_pool_reset() {
|
|
pool_ptr = 0;
|
|
}
|
|
|
|
void node_pool_destroy() {
|
|
if (pool) free(pool);
|
|
}
|
|
|
|
int node_pool_usage() {
|
|
return pool_ptr;
|
|
}
|
|
|
|
static void make_move(char move, Node* curr) {
|
|
int128_t na = curr->a, nb = curr->b, nc = curr->c;
|
|
|
|
/* Calculate the new triplet based on the move type */
|
|
if (move == 'A') {
|
|
na = 2 * (curr->b + curr->c) - curr->a;
|
|
} else if (move == 'B') {
|
|
nb = 2 * (curr->a + curr->c) - curr->b;
|
|
} else if (move == 'C') {
|
|
nc = 2 * (curr->a + curr->b) - curr->c;
|
|
}
|
|
|
|
/* Validation and Enqueue */
|
|
if (safe_val(na) && safe_val(nb) && safe_val(nc)) {
|
|
if (visit_and_mark(na, nb, nc)) {
|
|
if (pool_ptr >= pool_capacity) return; /* Pool safety */
|
|
Node* n = &pool[pool_ptr++];
|
|
n->a = na; n->b = nb; n->c = nc;
|
|
n->move = move;
|
|
n->parent = curr;
|
|
n->next = NULL;
|
|
q_push(n);
|
|
}
|
|
}
|
|
}
|
|
|
|
void try_push_children(Node* curr) {
|
|
char last = curr->move;
|
|
|
|
if (last == '\0') {
|
|
make_move('A', curr);
|
|
make_move('B', curr);
|
|
make_move('C', curr);
|
|
return;
|
|
}
|
|
|
|
if (last == 'A') {
|
|
make_move('C', curr);
|
|
make_move('B', curr);
|
|
}
|
|
else if (last == 'B') {
|
|
make_move('C', curr);
|
|
make_move('A', curr);
|
|
}
|
|
else if (last == 'C') {
|
|
make_move('B', curr);
|
|
make_move('A', curr);
|
|
}
|
|
}
|
|
|
|
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);
|
|
VisitedEntry* cur = hash_table[h];
|
|
while (cur) {
|
|
if (cur->a == a && cur->b == b && cur->c == c) return 0;
|
|
cur = cur->next;
|
|
}
|
|
|
|
if (visited_ptr >= pool_capacity) {
|
|
fprintf(stderr, "VisPool Overflow! Increase MAX_NODES.\n");
|
|
exit(1);
|
|
}
|
|
|
|
VisitedEntry* e = &visited_pool[visited_ptr++];
|
|
e->a = a; e->b = b; e->c = c;
|
|
e->next = hash_table[h];
|
|
hash_table[h] = e;
|
|
return 1;
|
|
}
|
|
|
|
void clear_hash_table() {
|
|
visited_ptr = 0;
|
|
for (size_t i = 0; i < HASH_SIZE; ++i) hash_table[i] = NULL;
|
|
} |