From 01f14089a5737c0fec5ccbd0612f63ff7132fa3e Mon Sep 17 00:00:00 2001 From: Sandeep Satheesh <sinchan4x496@gmail.com> Date: Mon, 24 Sep 2018 23:14:44 +0530 Subject: [PATCH 1/5] Add linear prime sieve --- .../linear-prime-sieve/linearPrimeSieve.js | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/algorithms/math/linear-prime-sieve/linearPrimeSieve.js diff --git a/src/algorithms/math/linear-prime-sieve/linearPrimeSieve.js b/src/algorithms/math/linear-prime-sieve/linearPrimeSieve.js new file mode 100644 index 0000000000..5d600ebe30 --- /dev/null +++ b/src/algorithms/math/linear-prime-sieve/linearPrimeSieve.js @@ -0,0 +1,24 @@ +/** + * @param {number} maxNumber + * @return {number[]} + */ +export default function linearPrimeSieve(maxNumber) { + const primes =[]; + const leastPrimeFactor = new Array(maxNumber + 1).fill(0); // leastPrimeFactor[i] gives us the least prime factor of 'i' + + for(let i=2; i<=maxNumber; i++ ){ + if(!leastPrimeFactor[i]){ // leastPrimeFactor[i] = 0 means 'i' itself is its least prime factor, i.e 'i' is prime + leastPrimeFactor[i] = i; + primes.push(i); + } + + /* + * start setting leastPrimeFactor[] for numbers 'x', where x = p * i, p is x's least prime factor and p <= leastPrimeFactor[i] + * x = p*i, this representation will be unique for any number, therefore leastPrimeFactor[x] will be set only once. + */ + for(let j=0; j<primes.length && primes[j]*i <=maxNumber && primes[j]<=leastPrimeFactor[i]; j++) + leastPrimeFactor[primes[j]*i] = primes[j]; + } + + return primes; +} From 786cd38228078b37cb09e87082c33d5f2d412ddd Mon Sep 17 00:00:00 2001 From: Sandeep Satheesh <sinchan4x496@gmail.com> Date: Mon, 24 Sep 2018 23:18:06 +0530 Subject: [PATCH 2/5] Adds README.md --- .../math/linear-prime-sieve/README.md | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/algorithms/math/linear-prime-sieve/README.md diff --git a/src/algorithms/math/linear-prime-sieve/README.md b/src/algorithms/math/linear-prime-sieve/README.md new file mode 100644 index 0000000000..b83aa39c77 --- /dev/null +++ b/src/algorithms/math/linear-prime-sieve/README.md @@ -0,0 +1,44 @@ +# Linear Prime Sieve + +Linear Prime Sieve is an algorithm for finding all prime numbers up to some limit `n` in linear time. + + + +## How it works + +1. Create an array `leastPrimeFactor` of `n + 1` positions filled with `0`(to represent the least prime factors of numbers `0` through `n`) +2. Start at position `i = 2` (the first prime number) +3. If the least prime factor of `i` is `0` it means `i` is a prime number, so we add it to our list of `primes`. +4. We start setting the least prime factor for numbers `x`, where x = `p` * `i`, `p` is `x`'s least prime factor and `p` <= `leastPrimeFactor(i)`, we do + this by traversing the list of primes accumulated till now. +5. Increment the value of `i`. +6. We repeat steps 3 through 5 until `i` exceeds `n`. + + +When the algorithm terminates, all the prime numbers from `0` through `n` will be added to our primes list + + + +## Complexity + +The algorithm has a complexity of `O(n)`. + + + +## Proof Of Correctness + +In order to prove the time complexity, we need to show that the alogrithm sets all leastPrimeFactor[] correctly, and that every value will be set only once. +If so the algorithm will have linear time complexity, since all the remaining work of the algorithm is of `O(n)`. +We Observe that every number `i` has exactly one representation of form: + `i = leastPrimeFactor[i] * x`, where leastPrimeFactor[i] <= leastPrimeFactor[x]. + +In our Alogrith, for every `x`, it goes through all prime numbers it could be multiplied by, i.e. all prime numbers up to leastPrimeFactor[x] inclusive, +in order to get the numbers in the form given above. +Hence, the algorithm will go through every composite number exactly once, setting the correct values for leastPrimeFactor[] there. + + + +## References + +- David Gries, Jayadev Misra. A Linear Sieve Algorithm for Finding Prime Numbers [1978]. +- [CP-Algorithms/Linear-Sieve](https://cp-algorithms.com/algebra/prime-sieve-linear.html). \ No newline at end of file From 65037f32ddb5f42d9bda4ae180a867971ec807c7 Mon Sep 17 00:00:00 2001 From: Sandeep Satheesh <sinchan4x496@gmail.com> Date: Mon, 24 Sep 2018 23:24:04 +0530 Subject: [PATCH 3/5] Adds linearPrimeSieve tests --- .../__test__/linearPrimeSieve.test.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/algorithms/math/linear-prime-sieve/__test__/linearPrimeSieve.test.js diff --git a/src/algorithms/math/linear-prime-sieve/__test__/linearPrimeSieve.test.js b/src/algorithms/math/linear-prime-sieve/__test__/linearPrimeSieve.test.js new file mode 100644 index 0000000000..7a419c5691 --- /dev/null +++ b/src/algorithms/math/linear-prime-sieve/__test__/linearPrimeSieve.test.js @@ -0,0 +1,12 @@ +import linearPrimeSieve from '../linearPrimeSieve'; + +describe('linearPrimeSieve', () => { + it('should find all primes less than or equal to n', () => { + expect(linearPrimeSieve(5)).toEqual([2, 3, 5]); + expect(linearPrimeSieve(10)).toEqual([2, 3, 5, 7]); + expect(linearPrimeSieve(100)).toEqual([ + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, + 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, + ]); + }); +}); \ No newline at end of file From b43738839e18f4f8a797cb5ad671192b244d04b4 Mon Sep 17 00:00:00 2001 From: Sandeep Satheesh <sinchan4x496@gmail.com> Date: Mon, 1 Oct 2018 22:35:42 +0530 Subject: [PATCH 4/5] Refactor linearPrimeSieve.js --- .../linear-prime-sieve/linearPrimeSieve.js | 47 ++++++++++++------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/src/algorithms/math/linear-prime-sieve/linearPrimeSieve.js b/src/algorithms/math/linear-prime-sieve/linearPrimeSieve.js index 5d600ebe30..611c469ae1 100644 --- a/src/algorithms/math/linear-prime-sieve/linearPrimeSieve.js +++ b/src/algorithms/math/linear-prime-sieve/linearPrimeSieve.js @@ -3,22 +3,33 @@ * @return {number[]} */ export default function linearPrimeSieve(maxNumber) { - const primes =[]; - const leastPrimeFactor = new Array(maxNumber + 1).fill(0); // leastPrimeFactor[i] gives us the least prime factor of 'i' - - for(let i=2; i<=maxNumber; i++ ){ - if(!leastPrimeFactor[i]){ // leastPrimeFactor[i] = 0 means 'i' itself is its least prime factor, i.e 'i' is prime - leastPrimeFactor[i] = i; - primes.push(i); - } - - /* - * start setting leastPrimeFactor[] for numbers 'x', where x = p * i, p is x's least prime factor and p <= leastPrimeFactor[i] - * x = p*i, this representation will be unique for any number, therefore leastPrimeFactor[x] will be set only once. - */ - for(let j=0; j<primes.length && primes[j]*i <=maxNumber && primes[j]<=leastPrimeFactor[i]; j++) - leastPrimeFactor[primes[j]*i] = primes[j]; - } - - return primes; + const primes = []; + // leastPrimeFactor[i] gives us the least prime factor of 'i' + const leastPrimeFactor = new Array(maxNumber + 1).fill(0); + + for (let i = 2; i <= maxNumber; i += 1) { + if (!leastPrimeFactor[i]) { + /* leastPrimeFactor[i] = 0 means 'i' itself is its least prime factor, + * i.e 'i' is prime + */ + leastPrimeFactor[i] = i; + primes.push(i); + } + + /* + * start setting leastPrimeFactor[] for numbers 'x', where x = p * i, p is x's + * least prime factor and p <= leastPrimeFactor[i]. x = p*i, this representation will + * be unique for any number, therefore leastPrimeFactor[x] will be + * set only once. + */ + + let j = 0; + while (j < primes.length) { + if ((primes[j] * i > maxNumber) || (primes[j] > leastPrimeFactor[i])) { break; } + leastPrimeFactor[primes[j] * i] = primes[j]; + j += 1; + } + } + + return primes; } From 49bdb355c93daa4fab9c5b8716e35e911e034a98 Mon Sep 17 00:00:00 2001 From: Sandeep Satheesh <sinchan4x496@gmail.com> Date: Mon, 1 Oct 2018 22:38:59 +0530 Subject: [PATCH 5/5] refactor linearPrimSieve.test.js as per eslint --- .../math/linear-prime-sieve/__test__/linearPrimeSieve.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algorithms/math/linear-prime-sieve/__test__/linearPrimeSieve.test.js b/src/algorithms/math/linear-prime-sieve/__test__/linearPrimeSieve.test.js index 7a419c5691..2e84028320 100644 --- a/src/algorithms/math/linear-prime-sieve/__test__/linearPrimeSieve.test.js +++ b/src/algorithms/math/linear-prime-sieve/__test__/linearPrimeSieve.test.js @@ -9,4 +9,4 @@ describe('linearPrimeSieve', () => { 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, ]); }); -}); \ No newline at end of file +});