Data update
This commit is contained in:
parent
4bb20c9b71
commit
cbaf4c4b64
12390 changed files with 318560 additions and 27248 deletions
240
Task/Home-primes/JavaScript/home-primes.js
Normal file
240
Task/Home-primes/JavaScript/home-primes.js
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
/**
|
||||
* Home Primes calculator - JavaScript version
|
||||
* Finds the home prime for a given number by repeatedly factorizing and concatenating
|
||||
*/
|
||||
|
||||
const CERTAINTY_LEVEL = 20;
|
||||
const PRIME_LIMIT = 10000;
|
||||
|
||||
class HomePrimes {
|
||||
constructor() {
|
||||
this.primes = [];
|
||||
this.listPrimes(PRIME_LIMIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function to calculate home primes for test values
|
||||
*/
|
||||
main() {
|
||||
const values = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 65];
|
||||
|
||||
for (const value of values) {
|
||||
let number = BigInt(value);
|
||||
const previousNumbers = [number];
|
||||
let searching = true;
|
||||
|
||||
while (searching) {
|
||||
number = this.concatenate(this.primeFactors(number));
|
||||
previousNumbers.push(number);
|
||||
|
||||
if (this.isProbablePrime(number, CERTAINTY_LEVEL)) {
|
||||
const lastIndex = previousNumbers.length - 1;
|
||||
let output = '';
|
||||
for (let k = lastIndex; k >= 1; k--) {
|
||||
output += `HP${previousNumbers[lastIndex - k]}(${k}) = `;
|
||||
}
|
||||
output += previousNumbers[lastIndex];
|
||||
console.log(output);
|
||||
searching = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get prime factors of a number using trial division or Pollard's Rho
|
||||
*/
|
||||
primeFactors(num) {
|
||||
if (num <= BigInt(PRIME_LIMIT * PRIME_LIMIT)) {
|
||||
return this.smallPrimeFactors(num);
|
||||
}
|
||||
|
||||
if (this.isProbablePrime(num, CERTAINTY_LEVEL)) {
|
||||
return [num];
|
||||
}
|
||||
|
||||
const divisor = this.pollardRho(num);
|
||||
const result = [
|
||||
...this.primeFactors(divisor),
|
||||
...this.primeFactors(num / divisor)
|
||||
];
|
||||
return result.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Trial division for smaller numbers
|
||||
*/
|
||||
smallPrimeFactors(num) {
|
||||
let number = Number(num);
|
||||
const result = [];
|
||||
|
||||
for (let i = 0; i < this.primes.length && number > 1; i++) {
|
||||
while (number % this.primes[i] === 0) {
|
||||
result.push(BigInt(this.primes[i]));
|
||||
number = Math.floor(number / this.primes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (number > 1) {
|
||||
result.push(BigInt(number));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pollard's Rho algorithm for integer factorization
|
||||
*/
|
||||
pollardRho(num) {
|
||||
// Check if even
|
||||
if ((num & BigInt(1)) === BigInt(0)) {
|
||||
return BigInt(2);
|
||||
}
|
||||
|
||||
const bitLength = num.toString(2).length;
|
||||
const constant = this.randomBigInt(bitLength);
|
||||
let x = this.randomBigInt(bitLength);
|
||||
let y = x;
|
||||
let divisor = BigInt(1);
|
||||
|
||||
while (divisor === BigInt(1)) {
|
||||
x = (x * x + constant) % num;
|
||||
y = (y * y + constant) % num;
|
||||
y = (y * y + constant) % num;
|
||||
divisor = this.gcd(x > y ? x - y : y - x, num);
|
||||
}
|
||||
|
||||
return divisor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate list of BigInts into a single BigInt
|
||||
*/
|
||||
concatenate(list) {
|
||||
const str = list.map(n => n.toString()).join('');
|
||||
return BigInt(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sieve of Eratosthenes to generate primes up to limit
|
||||
*/
|
||||
listPrimes(limit) {
|
||||
const sieve = new Array(limit + 1).fill(true);
|
||||
sieve[0] = false;
|
||||
sieve[1] = false;
|
||||
|
||||
for (let i = 2; i * i <= limit; i++) {
|
||||
if (sieve[i]) {
|
||||
for (let j = i * i; j <= limit; j += i) {
|
||||
sieve[j] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.primes = [];
|
||||
for (let i = 2; i <= limit; i++) {
|
||||
if (sieve[i]) {
|
||||
this.primes.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Miller-Rabin primality test
|
||||
*/
|
||||
isProbablePrime(n, k) {
|
||||
if (n === BigInt(2) || n === BigInt(3)) return true;
|
||||
if (n <= BigInt(1) || (n & BigInt(1)) === BigInt(0)) return false;
|
||||
|
||||
// Write n-1 as d * 2^r
|
||||
let d = n - BigInt(1);
|
||||
let r = 0;
|
||||
while ((d & BigInt(1)) === BigInt(0)) {
|
||||
d >>= BigInt(1);
|
||||
r++;
|
||||
}
|
||||
|
||||
// Witness loop
|
||||
for (let i = 0; i < k; i++) {
|
||||
const a = this.randomBigIntRange(BigInt(2), n - BigInt(2));
|
||||
let x = this.modPow(a, d, n);
|
||||
|
||||
if (x === BigInt(1) || x === n - BigInt(1)) continue;
|
||||
|
||||
let composite = true;
|
||||
for (let j = 0; j < r - 1; j++) {
|
||||
x = this.modPow(x, BigInt(2), n);
|
||||
if (x === n - BigInt(1)) {
|
||||
composite = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (composite) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modular exponentiation: (base^exp) % mod
|
||||
*/
|
||||
modPow(base, exp, mod) {
|
||||
let result = BigInt(1);
|
||||
base = base % mod;
|
||||
|
||||
while (exp > BigInt(0)) {
|
||||
if ((exp & BigInt(1)) === BigInt(1)) {
|
||||
result = (result * base) % mod;
|
||||
}
|
||||
exp >>= BigInt(1);
|
||||
base = (base * base) % mod;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Euclidean algorithm for GCD
|
||||
*/
|
||||
gcd(a, b) {
|
||||
a = a < BigInt(0) ? -a : a;
|
||||
b = b < BigInt(0) ? -b : b;
|
||||
|
||||
while (b !== BigInt(0)) {
|
||||
const temp = b;
|
||||
b = a % b;
|
||||
a = temp;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate random BigInt with specified bit length
|
||||
*/
|
||||
randomBigInt(bits) {
|
||||
const bytes = Math.ceil(bits / 8);
|
||||
const hex = Array(bytes)
|
||||
.fill(0)
|
||||
.map(() => Math.floor(Math.random() * 256).toString(16).padStart(2, '0'))
|
||||
.join('');
|
||||
const num = BigInt('0x' + hex);
|
||||
return num >> BigInt(bytes * 8 - bits); // Trim to exact bit length
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate random BigInt in range [min, max]
|
||||
*/
|
||||
randomBigIntRange(min, max) {
|
||||
const range = max - min + BigInt(1);
|
||||
const bits = range.toString(2).length;
|
||||
let result;
|
||||
do {
|
||||
result = this.randomBigInt(bits);
|
||||
} while (result >= range);
|
||||
return result + min;
|
||||
}
|
||||
}
|
||||
|
||||
// Run the program
|
||||
const hp = new HomePrimes();
|
||||
hp.main();
|
||||
Loading…
Add table
Add a link
Reference in a new issue