124 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			124 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ---
 | |
| id: 5900f39e1000cf542c50feb1
 | |
| title: 'Problema 50: Soma dos números primos consecutivos'
 | |
| challengeType: 5
 | |
| forumTopicId: 302161
 | |
| dashedName: problem-50-consecutive-prime-sum
 | |
| ---
 | |
| 
 | |
| # --description--
 | |
| 
 | |
| O número primo 41 pode ser escrito como a soma de seis números primos consecutivos:
 | |
| 
 | |
| <div style='text-align: center;'>41 = 2 + 3 + 5 + 7 + 11 + 13</div>
 | |
| 
 | |
| Esta é a soma mais longa de números primos consecutivos abaixo de 100 que resultam em um número primo.
 | |
| 
 | |
| A soma mais longa de números primos consecutivos abaixo de 1000 contém 21 termos e resulta em 953.
 | |
| 
 | |
| Qual número primo, abaixo de um milhão, é o resultado da soma da maior sequência de números primos?
 | |
| 
 | |
| # --hints--
 | |
| 
 | |
| `consecutivePrimeSum(1000)` deve retornar um número.
 | |
| 
 | |
| ```js
 | |
| assert(typeof consecutivePrimeSum(1000) === 'number');
 | |
| ```
 | |
| 
 | |
| `consecutivePrimeSum(1000)` deve retornar 953.
 | |
| 
 | |
| ```js
 | |
| assert.strictEqual(consecutivePrimeSum(1000), 953);
 | |
| ```
 | |
| 
 | |
| `consecutivePrimeSum(1000000)` deve retornar 997651.
 | |
| 
 | |
| ```js
 | |
| assert.strictEqual(consecutivePrimeSum(1000000), 997651);
 | |
| ```
 | |
| 
 | |
| # --seed--
 | |
| 
 | |
| ## --seed-contents--
 | |
| 
 | |
| ```js
 | |
| function consecutivePrimeSum(limit) {
 | |
| 
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| 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);
 | |
| 
 | |
| function isPrime(num) {
 | |
|   if (num === 2)
 | |
|     return true;
 | |
|   else if (num % 2 === 0)
 | |
|     return false
 | |
|   else
 | |
|     return PRIME_SIEVE[(num - 3) / 2];
 | |
| }
 | |
| 
 | |
| function consecutivePrimeSum(limit) {
 | |
|   // Initalize for longest sum < 100
 | |
|   let bestPrime = 41;
 | |
|   let bestI = 0;
 | |
|   let bestJ = 5;
 | |
| 
 | |
|   // Find longest sum < limit
 | |
|   let sumOfCurrRange = 41;
 | |
|   let i = 0, j = 5;
 | |
|   // -- Loop while current some starting at i is < limit
 | |
|   while (sumOfCurrRange < limit) {
 | |
|     let currSum = sumOfCurrRange;
 | |
|     // -- Loop while pushing j towards end of PRIMES list
 | |
|     //      keeping sum under limit
 | |
|     while (currSum < limit) {
 | |
|       if (isPrime(currSum)) {
 | |
|         bestPrime = sumOfCurrRange = currSum;
 | |
|         bestI = i;
 | |
|         bestJ = j;
 | |
|       }
 | |
|       // -- Increment inner loop
 | |
|       j++;
 | |
|       currSum += PRIMES[j];
 | |
|     }
 | |
|     // -- Increment outer loop
 | |
|     i++;
 | |
|     j = i + (bestJ - bestI);
 | |
|     sumOfCurrRange -= PRIMES[i - 1];
 | |
|     sumOfCurrRange += PRIMES[j];
 | |
|   }
 | |
|   // Return
 | |
|   return bestPrime;
 | |
| }
 | |
| ```
 |