diff --git a/Algorithms.ts b/Algorithms.ts index 0f5fe14..9d68f85 100644 --- a/Algorithms.ts +++ b/Algorithms.ts @@ -65,6 +65,73 @@ export function sqrtBig(value: bigint): bigint{ return x; } +//Generate an infinite sequence of prime numbers using the Sieve of Eratosthenes +export function* sieveOfEratosthenes(){ + //Return 2 the first time, this lets us skip all even numbers later + yield 2; + + //Dictionary to hold the primes we have already found + let dict = new Map(); + + //Start checking for primes with the number 3 and skip all even numbers + for(let possiblePrime = 3;true;possiblePrime += 2){ + //If possiblePrime is not in the dictionary it is a new prime number + //Return it and mark its next multiple + if(!dict.has(possiblePrime)){ + yield possiblePrime; + dict.set(possiblePrime * possiblePrime, [possiblePrime]); + } + //If possiblePrime is in the dictionary it is a composite number + else{ + //Move each witness to its next multiple + for(let num of dict.get(possiblePrime)){ + let loc: number = possiblePrime + num + num; + if(dict.has(loc)){ + dict.get(loc).push(num); + } + else{ + dict.set(loc, [num]); + } + //We no longer need this, free the memory + dict.delete(possiblePrime); + } + } + } +} + +export function* sieveOfEratosthenesBig(){ + //Return 2 the first time, this lets us skip all even numbers later + yield 2n; + + //Dictionary to hold the priems we have already found + let dict = new Map(); + + //Start checking for primes with the number 3 and skip all even numbers + for(let possiblePrime = 3n;true;possiblePrime += 2n){ + //If possiblePrime is not in the dictionary it is a new prime number + //Return it and mark its next multiple + if(!dict.has(possiblePrime)){ + yield possiblePrime; + dict.set(possiblePrime * possiblePrime, [possiblePrime]); + } + //If possiblePrime is in the dictionary it is a composite number + else{ + //Move each witness to its next multiple + for(let num of dict.get(possiblePrime)){ + let loc: bigint = possiblePrime + num + num; + if(dict.has(loc)){ + dict.get(loc).push(num); + } + else{ + dict.set(loc, [num]); + } + //We no longer need this, free the memory + dict.delete(possiblePrime); + } + } + } +} + export function getAllFib(goalNumber: number): number[]{ //Setup the variables let fibNums: number[] = []; diff --git a/TestAlgorithms.ts b/TestAlgorithms.ts index 7ebf024..9feb43a 100644 --- a/TestAlgorithms.ts +++ b/TestAlgorithms.ts @@ -22,8 +22,9 @@ Copyright (C) 2021 Matthew Ellison import assert = require("assert"); +import { nextTick } from "process"; import { arrayEquals, getAllFib, getAllFibBig, getFactors, getFactorsBig, getPrimes, getPrimesBig, getNumPrimes, getNumPrimesBig, - sqrtBig, getSum, getSumBig, getProd, getProdBig, getDivisors, getDivisorsBig, factorial, factorialBig, isPalindrome, toBin, toBinBig, isPrime, isPrimeBig } from "./Algorithms"; + sqrtBig, getSum, getSumBig, getProd, getProdBig, getDivisors, getDivisorsBig, factorial, factorialBig, isPalindrome, toBin, toBinBig, isPrime, isPrimeBig, sieveOfEratosthenes, sieveOfEratosthenesBig } from "./Algorithms"; function testArrayEquals(){ @@ -95,6 +96,34 @@ function testSqrtBig(){ console.log("testSqrtBig passed"); } +function testSieveOfEratosthenes(){ + //Test 1 + let sieve = sieveOfEratosthenes(); + let correctAnswer: number[] = [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]; + let answer: number[] = []; + for(let cnt = 0;cnt < 25;++cnt){ + let prime = sieve.next().value; + if(typeof prime == "number"){ + answer.push(prime); + } + } + assert.ok(arrayEquals(answer, correctAnswer), "sieveOfEratosthenes failed"); + + //Test 2 + let bigSieve = sieveOfEratosthenesBig(); + let bigCorrectAnswer: bigint[] = [2n, 3n, 5n, 7n, 11n, 13n, 17n, 19n, 23n, 29n, 31n, 37n, 41n, 43n, 47n, 53n, 59n, 61n, 67n, 71n, 73n, 79n, 83n, 89n, 97n]; + let bigAnswer: bigint[] = []; + for(let cnt = 0;cnt < 25;++cnt){ + let prime = bigSieve.next().value; + if(typeof prime == "bigint"){ + bigAnswer.push(prime); + } + } + assert.ok(arrayEquals(bigAnswer, bigCorrectAnswer), "sieveOfEratosthenes big failed"); + + console.log("sieveOfEratosthenes passed"); +} + function testGetAllFib(){ //Test 1 let correctAnswer = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]; @@ -359,6 +388,7 @@ function testToBin(){ //Run all of the tests testArrayEquals(); testSqrtBig(); +testSieveOfEratosthenes(); testGetAllFib(); testGetPrimes(); testGetNumPrimes();