Made an improvement for storing a global table for possible duplicate numbers (after dividing by gcd)
This commit is contained in:
+12
-5
@@ -5,6 +5,7 @@
|
||||
|
||||
extern int128_t LIMIT;
|
||||
extern int run_bfs(int128_t* sum, int128_t a0, int128_t b0, int128_t c0, int print_mode);
|
||||
extern int is_new_root(int128_t a, int128_t b, int128_t c);
|
||||
|
||||
const int NUM_PRIMES = 3;
|
||||
const int primes[] = {2, 3, 5};
|
||||
@@ -57,15 +58,21 @@ void generate_factor_pairs(int128_t* sum, int prime_index, int* exponents,
|
||||
if ((n1 + n2) % 2 == 0) {
|
||||
int128_t val1 = values[1] + values[2] + ((n1 + n2) >> 1);
|
||||
int128_t val2 = values[1] + values[2] - ((n1 + n2) >> 1);
|
||||
int128_t greater = values[2] >= val1 ? values[2] : val1;
|
||||
|
||||
int128_t gcd1 = gcd3(values[1], values[2], val1);
|
||||
int128_t gcd2 = gcd3(values[1], values[2], val2);
|
||||
int128_t r1a = values[1] / gcd1, r1b = values[2] / gcd1, r1c = val1 / gcd1;
|
||||
int128_t r2a = values[1] / gcd2, r2b = values[2] / gcd2, r2c = val2 / gcd2;
|
||||
|
||||
if (is_new_root(r1a, r1b, r1c)) {
|
||||
int128_t greater = values[2] >= val1 ? values[2] : val1;
|
||||
LIMIT = values[1] >= greater ? values[1] * greater / (2 * gcd1 * gcd1) : values[2] * val1 / (2 * gcd1 * gcd1);
|
||||
run_bfs(sum, values[1] / gcd1, values[2] / gcd1, val1 / gcd1, print_mode);
|
||||
if (val2 >= 0) {
|
||||
greater = values[2] >= val2 ? values[2] : val2;
|
||||
run_bfs(sum, r1a, r1b, r1c, print_mode);
|
||||
}
|
||||
if (val2 >= 0 && is_new_root(r2a, r2b, r2c)) {
|
||||
int128_t greater = values[2] >= val2 ? values[2] : val2;
|
||||
LIMIT = values[1] >= greater ? values[1] * greater / (2 * gcd2 * gcd2) : values[2] * val2 / (2 * gcd2 * gcd2);
|
||||
run_bfs(sum, values[1] / gcd2, values[2] / gcd2, val2 / gcd2, print_mode);
|
||||
run_bfs(sum, r2a, r2b, r2c, print_mode);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
+60
-11
@@ -7,6 +7,65 @@
|
||||
#define HASH_SIZE 200003
|
||||
int128_t LIMIT = 0;
|
||||
|
||||
typedef struct GlobalEntry {
|
||||
int128_t a, b, c;
|
||||
struct GlobalEntry* next;
|
||||
} GlobalEntry;
|
||||
|
||||
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) {
|
||||
sort_triplet(&a, &b, &c);
|
||||
unsigned int h = hash_three128((uint128_t)a, (uint128_t)b, (uint128_t)c);
|
||||
|
||||
GlobalEntry* cur = global_root_table[h];
|
||||
while (cur) {
|
||||
if (cur->a == a && cur->b == b && cur->c == c) return 0;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
GlobalEntry* e = malloc(sizeof(GlobalEntry));
|
||||
if (!e) return 1; // Fallback to running BFS if malloc fails
|
||||
e->a = a; e->b = b; e->c = c;
|
||||
e->next = global_root_table[h];
|
||||
global_root_table[h] = e;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Call this at the start of 'auto' mode
|
||||
void clear_global_table() {
|
||||
for (int i = 0; i < HASH_SIZE; i++) {
|
||||
GlobalEntry* cur = global_root_table[i];
|
||||
while (cur) {
|
||||
GlobalEntry* next = cur->next;
|
||||
free(cur);
|
||||
cur = next;
|
||||
}
|
||||
global_root_table[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct Node {
|
||||
int128_t a, b, c;
|
||||
char move;
|
||||
@@ -36,17 +95,6 @@ void clear_hash_table() {
|
||||
|
||||
int run_bfs(int128_t* sum, int128_t a0, int128_t b0, int128_t c0, int print_mode);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static int visit_and_mark(int128_t a, int128_t b, int128_t c) {
|
||||
unsigned int h = hash_three128(a,b,c);
|
||||
@@ -202,6 +250,7 @@ int main() {
|
||||
|
||||
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};
|
||||
int128_t values[3] = {4 * power(a0, p) * power(b0, p), power(a0, p), power(b0, p)};
|
||||
|
||||
Reference in New Issue
Block a user