Attempted to separate the snippets of code to small functions and each set of functions have its own file. Also made some improvements by using pools instead of constantly mallocing space.

This commit is contained in:
2026-05-07 02:00:15 +03:00
parent 00396f86fe
commit e3239bf564
15 changed files with 561 additions and 289 deletions
+17
View File
@@ -0,0 +1,17 @@
#ifndef BFS_H
#define BFS_H
#include "utils.h"
/**
* @brief Runs a BFS to find the minimum moves to reach a triplet with zero
* @param sum Pointer to store the sum of moves for the found solution
* @param a0 The initial value of a
* @param b0 The initial value of b
* @param c0 The initial value of c
* @param print_mode The mode for printing the results (1 for full, 2 for minimal)
* @return 1 if a solution is found, 0 otherwise
*/
int run_bfs(int128_t* sum, int128_t a0, int128_t b0, int128_t c0, int print_mode);
#endif /* BFS_H */
-16
View File
@@ -1,16 +0,0 @@
#ifndef CORE_H
#define CORE_H
__extension__ typedef __int128 int128_t;
__extension__ typedef unsigned __int128 uint128_t;
// Read 128 bit integers as string
int read_int128_triplet(const char* prompt, int128_t* a, int128_t* b, int128_t* c);
// Convert the read string into 128 bit integers
int128_t str_to_int128(const char* s);
// Print 128 but integers
void print_int128(int128_t n);
#endif
+25
View File
@@ -0,0 +1,25 @@
#ifndef HASH_H
#define HASH_H
#include "utils.h"
#define HASH_SIZE 2000003
/**
* @brief Hashes three 128-bit integers into a single unsigned int
* @param a The first integer
* @param b The second integer
* @param c The third integer
* @return A hash value for the three integers
*/
unsigned int hash_three128(uint128_t a, uint128_t b, uint128_t c);
/**
* @brief Sorts a triplet of 128-bit integers in ascending order
* @param a Pointer to the first integer
* @param b Pointer to the second integer
* @param c Pointer to the third integer
*/
void sort_triplet(int128_t* a, int128_t* b, int128_t* c);
#endif /* HASH_H */
Executable
+29
View File
@@ -0,0 +1,29 @@
#ifndef IO_H
#define IO_H
#include "utils.h"
/*
* @brief Reads three 128 bit integers from the user with a prompt
* @param prompt The message to display to the user before reading input
* @param a Pointer to store the first integer
* @param b Pointer to store the second integer
* @param c Pointer to store the third integer
* @return 0 on success, -1 on printf error, -2 on scanf error
*/
int read_int128_triplet(const char* prompt, int128_t* a, int128_t* b, int128_t* c);
/*
* @brief Converts a string to a 128 bit integer
* @param s The string to convert
* @return The converted 128 bit integer
*/
int128_t str_to_int128(const char* s);
/**
* @brief Prints a 128 bit integer
* @param n The integer to print
*/
void print_int128(int128_t n);
#endif
+53 -10
View File
@@ -1,28 +1,71 @@
#ifndef MATHS_H #ifndef MATHS_H
#define MATHS_H #define MATHS_H
#include "core.h" #include "utils.h"
// Check if a 128 bit integer is a prime number or not /**
int is_prime(int128_t n); * @brief Checks if a 128 bit integer is a prime number
* @param n The integer to check
* @return true if the integer is prime, false otherwise
*/
bool is_prime(int128_t n);
// Calculate the GCD for 3 128 bit integers /**
* @brief Checks if a 128 bit integer is within the safe limit
* @param x The integer to check
* @return true if the integer is within the safe limit, false otherwise
*/
bool safe_val(int128_t x);
/**
* @brief Calculates the GCD for 3 128 bit integers
* @param a The first integer
* @param b The second integer
* @param c The third integer
* @return The GCD of the three integers
*/
int128_t gcd3(int128_t a, int128_t b, int128_t c); int128_t gcd3(int128_t a, int128_t b, int128_t c);
// Calculate the GCD for 2 128 bit integers /**
* @brief Calculates the GCD for 2 128 bit integers
* @param a The first integer
* @param b The second integer
* @return The GCD of the two integers
*/
int128_t gcd2(int128_t a, int128_t b); int128_t gcd2(int128_t a, int128_t b);
// Return the absolute value of a 128 bit integer /**
* @brief Returns the absolute value of a 128 bit integer
* @param x The integer to get the absolute value of
* @return The absolute value of the integer
*/
int128_t abs128(int128_t x); int128_t abs128(int128_t x);
// Raise a number a certain exponent /**
* @brief Calculates b raised to the power of ex for 128 bit integers
* @param b The base integer
* @param ex The exponent integer
* @return The result of b raised to the power of ex
*/
int128_t power(int128_t b, int128_t ex); int128_t power(int128_t b, int128_t ex);
// Generate the factor pairs /**
* @brief Generates factor pairs for a 128 bit integer
* @param sum Pointer to store the sum of the factor pairs
* @param prime_index The index of the prime number to use
* @param exponents Pointer to the array of exponents
* @param values Pointer to the array of values
* @param n1 The first integer
* @param print_mode The mode for printing the results
*/
void generate_factor_pairs(int128_t* sum, int prime_index, int* exponents, void generate_factor_pairs(int128_t* sum, int prime_index, int* exponents,
int128_t* values, int128_t n1, int print_mode); int128_t* values, int128_t n1, int print_mode);
// Calculate the square root of an unsigned 128 bit integer /**
* @brief Calculates the square root of an unsigned 128 bit integer
* @param number The integer to calculate the square root of
* @return The square root of the integer
*/
uint128_t mysqrt_uint128(uint128_t number); uint128_t mysqrt_uint128(uint128_t number);
#endif #endif
+66
View File
@@ -0,0 +1,66 @@
#ifndef NODES_H
#define NODES_H
#include "utils.h"
typedef struct Node {
int128_t a, b, c;
char move;
struct Node* parent;
struct Node* next;
} Node;
/**
* @brief Initializes the node pool with a specified maximum number of nodes
* @param max_nodes The maximum number of nodes the pool can hold
*/
void node_pool_init(int max_nodes);
/**
* @brief Allocates a node from the pool
* @return A pointer to the allocated node, or NULL if the pool is exhausted
*/
Node* node_pool_alloc();
/**
* @brief Resets the node pool without freeing memory
*/
void node_pool_reset();
/**
* @brief Frees the node pool memory
*/
void node_pool_destroy();
/**
* @brief Returns the current usage of the node pool
* @return The number of nodes currently allocated from the pool
*/
int node_pool_usage();
/**
* @brief Tries to push child nodes based on the current node's move
* @param curr The current node
*/
void try_push_children(Node* curr);
typedef struct VisitedEntry {
int128_t a, b, c;
struct VisitedEntry* next;
} VisitedEntry;
/**
* @brief Marks a triplet as visited and checks if it's new
* @param a The first integer of the triplet
* @param b The second integer of the triplet
* @param c The third integer of the triplet
* @return 1 if the triplet is new and marked, 0 if it was already visited
*/
int visit_and_mark(int128_t a, int128_t b, int128_t c);
/**
* @brief Clears the hash table
*/
void clear_hash_table();
#endif /* NODES_H */
+41
View File
@@ -0,0 +1,41 @@
#ifndef QUEUE_H
#define QUEUE_H
#include "utils.h"
#include "node.h"
/**
* @brief Initializes the queue with a maximum number of elements
* @param max_elements The maximum number of elements the queue can hold
*/
void q_init(int max_elements);
/**
* @brief Pushes a node into the queue
* @param n The node to push into the queue
*/
void q_push(Node* n);
/**
* @brief Returns the node from the front of the queue
* @return The node from the front of the queue
*/
Node* q_pop();
/**
* @brief Returns the current size of the queue
* @return The current size of the queue
*/
int q_size();
/**
* @brief Clears the queue without freeing memory
*/
void q_clear();
/**
* @brief Reset the queue memory
*/
void q_destroy();
#endif
+9
View File
@@ -0,0 +1,9 @@
#ifndef UTILS_H
#define UTILS_H
#include <stdbool.h>
__extension__ typedef __int128 int128_t;
__extension__ typedef unsigned __int128 uint128_t;
#endif /* UTILS_H */
+77
View File
@@ -0,0 +1,77 @@
#include "bfs.h"
#include "node.h"
#include "queue.h"
#include "io.h"
#include <stdio.h>
#include <stdlib.h>
int run_bfs(int128_t* sum, int128_t a0, int128_t b0, int128_t c0, int print_mode) {
node_pool_reset();
q_clear();
clear_hash_table();
Node* root = node_pool_alloc();
if (!root) return 0;
root->a = a0; root->b = b0; root->c = c0;
root->move = '\0'; root->parent = NULL;
q_push(root);
visit_and_mark(a0, b0, c0);
Node* found = NULL;
while (q_size() > 0) {
Node* curr = q_pop();
/* Goal Check */
if (curr->a == 0 || curr->b == 0 || curr->c == 0) {
found = curr;
break;
}
try_push_children(curr);
}
if (!found) {
if (print_mode == 1) printf("No solution found.\n");
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);
return 1;
}
+15
View File
@@ -0,0 +1,15 @@
#include "hash.h"
unsigned int hash_three128(uint128_t a, uint128_t b, uint128_t c) {
uint128_t x = a + (uint128_t)0x9e3779b97f4a7c15ULL + ((uint128_t)0x9e3779b97f4a7c15ULL << 64);
x ^= b + ((uint128_t)0xbf58476d1ce4e5b9ULL + ((uint128_t)0xbf58476d1ce4e5b9ULL << 64)) + (x << 6) + (x >> 2);
x ^= c + ((uint128_t)0x94d049bb133111ebULL + ((uint128_t)0x94d049bb133111ebULL << 64)) + (x << 6) + (x >> 2);
return (unsigned int)(x % HASH_SIZE);
}
void sort_triplet(int128_t* a, int128_t* b, int128_t* c) {
int128_t tmp;
if (*a > *b) { tmp = *a; *a = *b; *b = tmp; }
if (*b > *c) { tmp = *b; *b = *c; *c = tmp; }
if (*a > *b) { tmp = *a; *a = *b; *b = tmp; }
}
+1 -1
View File
@@ -1,4 +1,4 @@
#include "core.h" #include "io.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
+12 -7
View File
@@ -10,13 +10,18 @@ extern int is_new_root(int128_t a, int128_t b, int128_t c);
const int NUM_PRIMES = 3; const int NUM_PRIMES = 3;
const int primes[] = {2, 3, 5}; const int primes[] = {2, 3, 5};
int is_prime(int128_t n) { bool is_prime(int128_t n) {
if (n < 2) return 0; if (n < 2) return false;
if (n == 2) return 1; if (n == 2) return true;
if (n % 2 == 0) return 0; if (n % 2 == 0) return false;
for (int128_t i = 3; i <= n / i; i += 2) for (int128_t i = 3; i <= n / i; i += 2)
if (n % i == 0) return 0; if (n % i == 0) return false;
return 1; return true;
}
bool safe_val(int128_t x) {
if (x > LIMIT || x < -LIMIT) return false;
return true;
} }
int128_t gcd3(int128_t a, int128_t b, int128_t c) { int128_t gcd3(int128_t a, int128_t b, int128_t c) {
@@ -50,7 +55,7 @@ int128_t power(int128_t b, int128_t ex) {
} }
void generate_factor_pairs(int128_t* sum, int prime_index, int* exponents, void generate_factor_pairs(int128_t* sum, int prime_index, int* exponents,
int128_t* values, int128_t n1, int print_mode) { int128_t* values, int128_t n1, int print_mode) {
if (prime_index == NUM_PRIMES) { if (prime_index == NUM_PRIMES) {
int128_t n2 = values[0] / n1; int128_t n2 = values[0] / n1;
if (n1 > n2) return; if (n1 > n2) return;
+123
View File
@@ -0,0 +1,123 @@
#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;
}
+63
View File
@@ -0,0 +1,63 @@
#include "queue.h"
#include <stdio.h>
#include <stdlib.h>
static Node* q_front = NULL;
static Node* q_back = NULL;
static int current_size = 0;
static int capacity = 0;
void q_init(int max_elements) {
capacity = max_elements;
q_front = NULL;
q_back = NULL;
current_size = 0;
}
void q_push(Node* n) {
if (current_size >= capacity) return; /* Pool safety */
/* Exact logic from your 'enqueue' function */
n->next = NULL;
if (!q_back) {
q_front = q_back = n;
} else {
q_back->next = n;
q_back = n;
}
current_size++;
}
Node* q_pop() {
/* Exact logic from your 'dequeue' function */
if (!q_front) return NULL;
Node* r = q_front;
q_front = q_front->next;
if (!q_front) {
q_back = NULL;
}
r->next = NULL; /* Clean up the link */
current_size--;
return r;
}
int q_size() {
return current_size;
}
void q_clear() {
q_front = NULL;
q_back = NULL;
current_size = 0;
}
void q_destroy() {
q_front = NULL;
q_back = NULL;
current_size = 0;
capacity = 0;
}
Executable → Regular
+30 -255
View File
@@ -1,12 +1,15 @@
#include "core.h" #include "utils.h"
#include "maths.h" #include "maths.h"
#include "hash.h"
#include "node.h"
#include "queue.h"
#include "bfs.h"
#include "io.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#define HASH_SIZE 2000003 int LIMIT = 0;
#define MAX_NODES 40000000 // 40 Million nodes (~4.5GB RAM)
int128_t LIMIT = 0;
typedef struct GlobalEntry { typedef struct GlobalEntry {
int128_t a, b, c; int128_t a, b, c;
@@ -15,27 +18,6 @@ typedef struct GlobalEntry {
static GlobalEntry* global_root_table[HASH_SIZE] = {0}; static GlobalEntry* global_root_table[HASH_SIZE] = {0};
// Helper to sort the triplet so order doesn't matter
static void sort_triplet(int128_t* a, int128_t* b, int128_t* c) {
int128_t tmp;
if (*a > *b) { tmp = *a; *a = *b; *b = tmp; }
if (*b > *c) { tmp = *b; *b = *c; *c = tmp; }
if (*a > *b) { tmp = *a; *a = *b; *b = tmp; }
}
static inline uint128_t mix128(uint128_t a, uint128_t b, uint128_t c) {
uint128_t x = a + (uint128_t)0x9e3779b97f4a7c15ULL + ((uint128_t)0x9e3779b97f4a7c15ULL << 64);
x ^= b + ((uint128_t)0xbf58476d1ce4e5b9ULL + ((uint128_t)0xbf58476d1ce4e5b9ULL << 64)) + (x << 6) + (x >> 2);
x ^= c + ((uint128_t)0x94d049bb133111ebULL + ((uint128_t)0x94d049bb133111ebULL << 64)) + (x << 6) + (x >> 2);
return x;
}
static unsigned int hash_three128(uint128_t a, uint128_t b, uint128_t c) {
uint128_t x = mix128(a, b, c);
return (unsigned int)(x % HASH_SIZE);
}
// Returns 1 if this is a new root, 0 if we've already calculated it
int is_new_root(int128_t a, int128_t b, int128_t c) { int is_new_root(int128_t a, int128_t b, int128_t c) {
sort_triplet(&a, &b, &c); sort_triplet(&a, &b, &c);
unsigned int h = hash_three128((uint128_t)a, (uint128_t)b, (uint128_t)c); unsigned int h = hash_three128((uint128_t)a, (uint128_t)b, (uint128_t)c);
@@ -47,14 +29,13 @@ int is_new_root(int128_t a, int128_t b, int128_t c) {
} }
GlobalEntry* e = malloc(sizeof(GlobalEntry)); GlobalEntry* e = malloc(sizeof(GlobalEntry));
if (!e) return 1; // Fallback to running BFS if malloc fails if (!e) return 1; /* Fallback to running BFS if malloc fails */
e->a = a; e->b = b; e->c = c; e->a = a; e->b = b; e->c = c;
e->next = global_root_table[h]; e->next = global_root_table[h];
global_root_table[h] = e; global_root_table[h] = e;
return 1; return 1;
} }
// Call this at the start of 'auto' mode
void clear_global_table() { void clear_global_table() {
for (int i = 0; i < HASH_SIZE; i++) { for (int i = 0; i < HASH_SIZE; i++) {
GlobalEntry* cur = global_root_table[i]; GlobalEntry* cur = global_root_table[i];
@@ -67,220 +48,14 @@ void clear_global_table() {
} }
} }
typedef struct Node {
int128_t a, b, c;
char move;
struct Node* parent;
struct Node* next;
} Node;
typedef struct VisEntry {
int128_t a, b, c;
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() {
vis_ptr = 0;
for (size_t i = 0; i < HASH_SIZE; ++i) hash_table[i] = NULL;
}
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;
}
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 void enqueue(Node* n) {
n->next = NULL;
if (!q_back) q_front = q_back = n;
else {
q_back->next = n;
q_back = n;
}
}
static Node* dequeue() {
if (!q_front) return NULL;
Node* r = q_front;
q_front = q_front->next;
if (!q_front) q_back = NULL;
r->next = NULL;
return r;
}
static int safe_val(int128_t x) {
if (x > LIMIT || x < -LIMIT) return 0;
return 1;
}
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 (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;
n->next = NULL;
enqueue(n);
}
}
}
static void try_push_children(Node* curr) {
char last = curr->move;
// Root node doesn't have a 'last' move, so try all three.
if (last == '\0') {
make_move('A', curr);
make_move('B', curr);
make_move('C', curr);
return;
}
// To avoid AAAA, BBBB, or CCCC, we only pick from the other two moves.
// We also prioritize B and C to favor the alternating CBCB pattern.
if (last == 'A') {
// Just did A: try C then B (the two non-A moves)
make_move('C', curr);
make_move('B', curr);
}
else if (last == 'B') {
// Just did B: try C (alternating) then A (neutral)
// We skip B because it would just take us back to the parent.
make_move('C', curr);
make_move('A', curr);
}
else if (last == 'C') {
// Just did C: try B (alternating) then A (neutral)
// We skip C because it's redundant.
make_move('B', curr);
make_move('A', 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_init(20000000);
node_pool = malloc(sizeof(Node) * MAX_NODES); q_init(20000000);
vis_pool = malloc(sizeof(VisEntry) * MAX_NODES);
if (!node_pool || !vis_pool) { int mode = 0, print_mode = 0;
fprintf(stderr, "Failed to allocate memory pools. Try a smaller MAX_NODES.\n"); int128_t a0 = 10, b0 = 6, c0 = 0, sum = 0;
return 1;
}
int mode = 0, print_mode = 0; while (mode == 0) {
int128_t a0 = 10, b0 = 6, c0 = 0, sum = 0;
while (mode == 0) {
if (printf("1: manual\n") < 0) return 1; if (printf("1: manual\n") < 0) return 1;
if (printf("2: auto\n") < 0) return 1; if (printf("2: auto\n") < 0) return 1;
if (printf("Choose what mode you want to enter: ") < 0) return 1; if (printf("Choose what mode you want to enter: ") < 0) return 1;
@@ -289,9 +64,9 @@ int main() {
return 1; return 1;
} }
if (mode != 1 && mode != 2) mode = 0; if (mode != 1 && mode != 2) mode = 0;
} }
while (print_mode == 0) { while (print_mode == 0) {
if (printf("1: Print full?\n") < 0) return 1; if (printf("1: Print full?\n") < 0) return 1;
if (printf("2: Print minimal?\n") < 0) return 1; if (printf("2: Print minimal?\n") < 0) return 1;
if (printf("Choose what mode you want to enter: ") < 0) return 1; if (printf("Choose what mode you want to enter: ") < 0) return 1;
@@ -302,7 +77,7 @@ int main() {
if (print_mode != 1 && print_mode != 2) print_mode = 0; if (print_mode != 1 && print_mode != 2) print_mode = 0;
} }
if (mode == 1) { if (mode == 1) {
if (read_int128_triplet("Enter initial a b c:", &a0, &b0, &c0) != 0) { if (read_int128_triplet("Enter initial a b c:", &a0, &b0, &c0) != 0) {
fprintf(stderr, "Input error.\n"); fprintf(stderr, "Input error.\n");
return 1; return 1;
@@ -315,20 +90,17 @@ int main() {
print_int128(c0); printf(")\n"); print_int128(c0); printf(")\n");
return 0; return 0;
} }
int128_t gcd = gcd3(a0, b0, c0);
int128_t a = a0 / gcd, b = b0 / gcd, c = c0 / gcd;
int128_t greater = b >= c ? b : c;
LIMIT = a >= greater ? a * greater : b * c;
int128_t greater = b0 >= c0 ? b0 : c0; run_bfs(&sum, a, b, c, print_mode);
int128_t gcd = gcd3(a0, b0, c0); }
LIMIT = a0 >= greater ? a0 * greater / (2 * gcd * gcd) : b0 * c0 / (2 * gcd * gcd); else if (mode == 2) {
clear_global_table(); /* Reset unique root tracker */
if (!safe_val(a0) || !safe_val(b0) || !safe_val(c0)) { int p = 6;
fprintf(stderr, "Initial values exceed safe limit.\n");
return 1;
}
run_bfs(&sum, a0 / gcd, b0 / gcd, c0 / gcd, print_mode);
} else if (mode == 2) {
clear_global_table(); // Reset unique root tracker
int p = 3;
int exponents[3] = {2*p + 2, p, p}; int exponents[3] = {2*p + 2, p, p};
int128_t values[3] = {4 * power(a0, p) * power(b0, p), power(a0, p), power(b0, p)}; int128_t values[3] = {4 * power(a0, p) * power(b0, p), power(a0, p), power(b0, p)};
generate_factor_pairs(&sum, 0, exponents, values, 1, print_mode); generate_factor_pairs(&sum, 0, exponents, values, 1, print_mode);
@@ -336,5 +108,8 @@ int main() {
printf("Total sum is: "); printf("Total sum is: ");
print_int128(sum); printf("\n"); print_int128(sum); printf("\n");
} }
return 0;
node_pool_destroy();
q_destroy();
return 0;
} }