Made an improvement for storing a global table for possible duplicate numbers (after dividing by gcd)
This commit is contained in:
+13
-6
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
extern int128_t LIMIT;
|
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 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 NUM_PRIMES = 3;
|
||||||
const int primes[] = {2, 3, 5};
|
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) {
|
if ((n1 + n2) % 2 == 0) {
|
||||||
int128_t val1 = values[1] + values[2] + ((n1 + n2) >> 1);
|
int128_t val1 = values[1] + values[2] + ((n1 + n2) >> 1);
|
||||||
int128_t val2 = 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 gcd1 = gcd3(values[1], values[2], val1);
|
||||||
int128_t gcd2 = gcd3(values[1], values[2], val2);
|
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);
|
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);
|
run_bfs(sum, r1a, r1b, r1c, print_mode);
|
||||||
if (val2 >= 0) {
|
}
|
||||||
greater = values[2] >= val2 ? values[2] : val2;
|
if (val2 >= 0 && is_new_root(r2a, r2b, r2c)) {
|
||||||
LIMIT =values[1] >= greater ? values[1] * greater / (2 * gcd2 * gcd2) : values[2] * val2 / (2 * gcd2 * gcd2);
|
int128_t greater = values[2] >= val2 ? values[2] : val2;
|
||||||
run_bfs(sum, values[1] / gcd2, values[2] / gcd2, val2 / gcd2, print_mode);
|
LIMIT = values[1] >= greater ? values[1] * greater / (2 * gcd2 * gcd2) : values[2] * val2 / (2 * gcd2 * gcd2);
|
||||||
|
run_bfs(sum, r2a, r2b, r2c, print_mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|||||||
+60
-11
@@ -7,6 +7,65 @@
|
|||||||
#define HASH_SIZE 200003
|
#define HASH_SIZE 200003
|
||||||
int128_t LIMIT = 0;
|
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 {
|
typedef struct Node {
|
||||||
int128_t a, b, c;
|
int128_t a, b, c;
|
||||||
char move;
|
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);
|
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) {
|
static int visit_and_mark(int128_t a, int128_t b, int128_t c) {
|
||||||
unsigned int h = hash_three128(a,b,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);
|
run_bfs(&sum, a0 / gcd, b0 / gcd, c0 / gcd, print_mode);
|
||||||
} else if (mode == 2) {
|
} else if (mode == 2) {
|
||||||
|
clear_global_table(); // Reset unique root tracker
|
||||||
int p = 3;
|
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)};
|
||||||
|
|||||||
Reference in New Issue
Block a user