fix(curriculum): Faster Euler tests for prime seive problems (#48158)

This commit is contained in:
Jeremy L Thompson
2022-10-21 11:25:42 -06:00
committed by GitHub
parent 326e00fab8
commit 33a95e4e10
4 changed files with 140 additions and 98 deletions

View File

@@ -56,46 +56,57 @@ hexagonalTile(10);
# --solutions--
```js
const NUM_PRIMES = 840000;
const PRIME_SEIVE = Array(Math.floor((NUM_PRIMES-1)/2)).fill(true);
(function initPrimes(num) {
const upper = Math.floor((num - 1) / 2);
const sqrtUpper = Math.floor((Math.sqrt(num) - 1) / 2);
for (let i = 0; i <= sqrtUpper; i++) {
if (PRIME_SEIVE[i]) {
// Mark value in PRIMES array
const prime = 2 * i + 3;
// Mark all multiples of this number as false (not prime)
const primeSqaredIndex = 2 * i ** 2 + 6 * i + 3;
for (let j = primeSqaredIndex; j < upper; j += prime) {
PRIME_SEIVE[j] = false;
class PrimeSeive {
constructor(num) {
const seive = Array(Math.floor((num - 1) / 2)).fill(true);
const upper = Math.floor((num - 1) / 2);
const sqrtUpper = Math.floor((Math.sqrt(num) - 1) / 2);
for (let i = 0; i <= sqrtUpper; i++) {
if (seive[i]) {
// Mark value in seive array
const prime = 2 * i + 3;
// Mark all multiples of this number as false (not prime)
const primeSqaredIndex = 2 * i ** 2 + 6 * i + 3;
for (let j = primeSqaredIndex; j < upper; j += prime) {
seive[j] = false;
}
}
}
}
})(NUM_PRIMES);
function isPrime(num) {
if (num === 2) return true;
else if (num % 2 === 0) return false
else return PRIME_SEIVE[(num - 3) / 2];
}
this._seive = seive;
}
isPrime(num) {
return num === 2
? true
: num % 2 === 0
? false
: this.isOddPrime(num);
}
isOddPrime(num) {
return this._seive[(num - 3) / 2];
}
};
function hexagonalTile(tileIndex) {
const primeSeive = new PrimeSeive(tileIndex * 420);
let count = 1;
let n = 1;
let number = 0;
while (count < tileIndex) {
if (isPrime(6*n - 1) &&
isPrime(6*n + 1) &&
isPrime(12*n + 5)) {
if (primeSeive.isPrime(6*n - 1) &&
primeSeive.isPrime(6*n + 1) &&
primeSeive.isPrime(12*n + 5)) {
number = 3*n*n - 3*n + 2;
count++;
if (count >= tileIndex) break;
}
if (isPrime(6*n + 5) &&
isPrime(6*n - 1) &&
isPrime(12*n - 7) && n != 1) {
if (primeSeive.isPrime(6*n + 5) &&
primeSeive.isPrime(6*n - 1) &&
primeSeive.isPrime(12*n - 7) && n != 1) {
number = 3*n*n + 3*n + 1;
count++;
}

View File

@@ -67,25 +67,28 @@ distinctPrimeFactors(4, 4);
# --solutions--
```js
// Initalize factor count with seive
const NUMFACTORS = Array(135000).fill(0);
(function initFactors(num) {
for (let i = 2; i < num; i++)
if (NUMFACTORS[i] === 0)
for (let j = i; j < num; j += i)
NUMFACTORS[j]++;
})(135000);
function distinctPrimeFactors(targetNumPrimes, targetConsecutive) {
const primeLimit = targetNumPrimes * targetConsecutive * 10000;
const numFactors = Array(primeLimit).fill(0);
let numConsecutive = 0;
let currNumber = 10;
while (numConsecutive < targetConsecutive) {
if (NUMFACTORS[currNumber] === targetNumPrimes)
for (let i = 2; i < primeLimit; i++) {
if (numFactors[i] === targetNumPrimes) {
// Current number is composite with target num factors
numConsecutive++;
else
if (numConsecutive === targetConsecutive) {
return i - numConsecutive + 1;
}
} else {
// Current number is not matching composite
numConsecutive = 0;
currNumber++;
if (numFactors[i] === 0) {
// Current number is prime
for (let j = i; j < primeLimit; j += i) {
numFactors[j]++;
}
}
}
}
return currNumber - targetConsecutive;
}
```

View File

@@ -54,40 +54,56 @@ consecutivePrimeSum(1000000);
# --solutions--
```js
// Initalize prime number list with sieve
const NUM_PRIMES = 1000000;
const PRIMES = [2];
const PRIME_SIEVE = Array(Math.floor((NUM_PRIMES-1)/2)).fill(true);
(function initPrimes(num) {
const upper = Math.floor((num - 1) / 2);
const sqrtUpper = Math.floor((Math.sqrt(num) - 1) / 2);
for (let i = 0; i <= sqrtUpper; i++) {
if (PRIME_SIEVE[i]) {
// Mark value in PRIMES array
const prime = 2 * i + 3;
PRIMES.push(prime);
// Mark all multiples of this number as false (not prime)
const primeSqaredIndex = 2 * i ** 2 + 6 * i + 3;
for (let j = primeSqaredIndex; j < upper; j += prime)
PRIME_SIEVE[j] = false;
}
}
for (let i = sqrtUpper + 1; i < upper; i++) {
if (PRIME_SIEVE[i])
PRIMES.push(2 * i + 3);
}
})(NUM_PRIMES);
class PrimeSeive {
constructor(num) {
const seive = Array(Math.floor((num - 1) / 2)).fill(true);
const primes = [2];
const upper = Math.floor((num - 1) / 2);
const sqrtUpper = Math.floor((Math.sqrt(num) - 1) / 2);
function isPrime(num) {
if (num === 2)
return true;
else if (num % 2 === 0)
return false
else
return PRIME_SIEVE[(num - 3) / 2];
}
for (let i = 0; i <= sqrtUpper; i++) {
if (seive[i]) {
// Mark value in seive array
const prime = 2 * i + 3;
primes.push(prime);
// Mark all multiples of this number as false (not prime)
const primeSqaredIndex = 2 * i ** 2 + 6 * i + 3;
for (let j = primeSqaredIndex; j < upper; j += prime) {
seive[j] = false;
}
}
}
for (let i = sqrtUpper + 1; i < upper; i++) {
if (seive[i]) {
primes.push(2 * i + 3);
}
}
this._seive = seive;
this._primes = primes;
}
isPrime(num) {
return num === 2
? true
: num % 2 === 0
? false
: this.isOddPrime(num);
}
isOddPrime(num) {
return this._seive[(num - 3) / 2];
}
get primes() {
return this._primes;
}
};
function consecutivePrimeSum(limit) {
// Initalize seive
const primeSeive = new PrimeSeive(limit);
// Initalize for longest sum < 100
let bestPrime = 41;
let bestI = 0;
@@ -102,20 +118,20 @@ function consecutivePrimeSum(limit) {
// -- Loop while pushing j towards end of PRIMES list
// keeping sum under limit
while (currSum < limit) {
if (isPrime(currSum)) {
if (primeSeive.isPrime(currSum)) {
bestPrime = sumOfCurrRange = currSum;
bestI = i;
bestJ = j;
}
// -- Increment inner loop
j++;
currSum += PRIMES[j];
currSum += primeSeive.primes[j];
}
// -- Increment outer loop
i++;
j = i + (bestJ - bestI);
sumOfCurrRange -= PRIMES[i - 1];
sumOfCurrRange += PRIMES[j];
sumOfCurrRange -= primeSeive.primes[i - 1];
sumOfCurrRange += primeSeive.primes[j];
}
// Return
return bestPrime;

View File

@@ -56,31 +56,43 @@ primeDigitReplacements(6);
# --solutions--
```js
const NUM_PRIMES = 1000000;
const PRIME_SEIVE = Array(Math.floor((NUM_PRIMES-1)/2)).fill(true);
(function initPrimes(num) {
const upper = Math.floor((num - 1) / 2);
const sqrtUpper = Math.floor((Math.sqrt(num) - 1) / 2);
for (let i = 0; i <= sqrtUpper; i++) {
if (PRIME_SEIVE[i]) {
// Mark value in PRIMES array
const prime = 2 * i + 3;
// Mark all multiples of this number as false (not prime)
const primeSqaredIndex = 2 * i ** 2 + 6 * i + 3;
for (let j = primeSqaredIndex; j < upper; j += prime) {
PRIME_SEIVE[j] = false;
class PrimeSeive {
constructor(num) {
const seive = Array(Math.floor((num - 1) / 2)).fill(true);
const upper = Math.floor((num - 1) / 2);
const sqrtUpper = Math.floor((Math.sqrt(num) - 1) / 2);
for (let i = 0; i <= sqrtUpper; i++) {
if (seive[i]) {
// Mark value in seive array
const prime = 2 * i + 3;
// Mark all multiples of this number as false (not prime)
const primeSqaredIndex = 2 * i ** 2 + 6 * i + 3;
for (let j = primeSqaredIndex; j < upper; j += prime) {
seive[j] = false;
}
}
}
}
})(NUM_PRIMES);
function isPrime(num) {
if (num === 2) return true;
else if (num % 2 === 0) return false
else return PRIME_SEIVE[(num - 3) / 2];
}
this._seive = seive;
}
isPrime(num) {
return num === 2
? true
: num % 2 === 0
? false
: this.isOddPrime(num);
}
isOddPrime(num) {
return this._seive[(num - 3) / 2];
}
};
function primeDigitReplacements(n) {
const primeSeive = new PrimeSeive(n * n * n * 2000);
function isNFamily(number, n) {
const prime = number.toString();
const lastDigit = prime[prime.length - 1];
@@ -114,12 +126,12 @@ function primeDigitReplacements(n) {
function isPartOfFamily(number, prime) {
return (
isPrime(number) && number.toString().length === prime.length
primeSeive.isPrime(number) && number.toString().length === prime.length
);
}
for (let number = 1; number < 125000; number++) {
if (isPrime(number) && isNFamily(number, n)) {
if (primeSeive.isPrime(number) && isNFamily(number, n)) {
return number;
}
}