-
-
Notifications
You must be signed in to change notification settings - Fork 408
/
Copy pathprimes.ts
87 lines (76 loc) · 2.2 KB
/
primes.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/**
* Implementation of the Sieve of Eratosthenes algorithm.
*
* @param limit An integer _n_ > 1
* @returns All prime numbers from 2 through {@link limit}
*
* @see https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
*/
export function sieveOfEratosthenes(limit: number): number[] {
if (!Number.isInteger(limit) || limit <= 1) {
throw new Error('limit should be an integer greater than 1')
}
const maybePrime: boolean[] = new Array(limit + 1).fill(true)
for (let i = 2; i * i <= limit; i++) {
if (!maybePrime[i]) continue
for (let j = i * i; j <= limit; j += i) {
maybePrime[j] = false
}
}
const primes: number[] = []
for (let i = 2; i < maybePrime.length; i++) {
if (maybePrime[i]) {
primes.push(i)
}
}
return primes
}
/**
* Generator that yields primes.
*
* Inspired by https://gist.github.com/e-nikolov/cd94db0de2a6b70da144124ae93a6458
*/
export function* primeGenerator() {
type NumberGen = Generator<number, void, any>
function* filter(input: NumberGen, prime: number): NumberGen {
while (true) {
const { done, value } = input.next()
if (done) break
if (value % prime !== 0) yield value
}
}
let chain: NumberGen = (function* () {
let i = 2
while (true) yield i++
})()
while (true) {
const { done, value } = chain.next()
if (done) break
yield value
chain = filter(chain, value)
}
}
/**
* @function isPrime
* @description Determine if given number is prime.
* @param {number} num - A natural number.
* @return {boolean} - Whether the given number is prime.
* @see https://en.wikipedia.org/wiki/Prime_number
* @example isPrime(2) = false
* @example isPrime(3) = true
*/
export const isPrime = (num: number): boolean => {
// raise corresponding errors upon invalid inputs
if (num <= 0 || !Number.isInteger(num)) {
throw new Error('only natural numbers are supported')
}
// handle input being 1
if (num === 1) return false
// iterate from 2 to the square root of num to find a factor
// return false upon finding a factor
for (let i = 2; i <= Math.sqrt(num); i++) {
if (num % i === 0) return false
}
// if the entire loop runs without finding a factor, return true
return true
}