Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(maths): adds prime sieve and generator #144

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 69 additions & 5 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,79 @@
* [Xor Cipher](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/ciphers/xor_cipher.ts)

## Data Structures
* [Array Queue](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/array_queue.ts)
* [Linked Queue](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/linked_queue.ts)
* [Queue](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/queue.ts)
* [Stack](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/stack.ts)
* [Stack Queue](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/stack_queue.ts)
* Disjoint Set
* [Disjoint Set](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/disjoint_set/disjoint_set.ts)
* Test
* [Disjoint Set.Test](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/disjoint_set/test/disjoint_set.test.ts)
* Heap
* [Heap](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/heap/heap.ts)
* Test
* [Max Heap.Test](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/heap/test/max_heap.test.ts)
* [Min Heap.Test](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/heap/test/min_heap.test.ts)
* List
* [Doubly Linked List](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/list/doubly_linked_list.ts)
* [Linked List](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/list/linked_list.ts)
* [Singly Linked List](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/list/singly_linked_list.ts)
* Test
* [Doubly Linked List.Test](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/list/test/doubly_linked_list.test.ts)
* [Linked List](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/list/test/linked_list.ts)
* [Singly Linked List.Test](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/list/test/singly_linked_list.test.ts)
* Map
* [Hash Map](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/map/hash_map.ts)
* [Map](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/map/map.ts)
* Test
* [Hash Map.Test](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/map/test/hash_map.test.ts)
* Queue
* [Array Queue](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/queue/array_queue.ts)
* [Circular Queue](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/queue/circular_queue.ts)
* [Linked Queue](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/queue/linked_queue.ts)
* [Queue](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/queue/queue.ts)
* [Stack Queue](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/queue/stack_queue.ts)
* Test
* [Array Queue.Test](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/queue/test/array_queue.test.ts)
* [Circular Queue.Test](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/queue/test/circular_queue.test.ts)
* [Linked Queue.Test](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/queue/test/linked_queue.test.ts)
* [Queue](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/queue/test/queue.ts)
* [Stack Queue.Test](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/queue/test/stack_queue.test.ts)
* Set
* [Hash Map Set](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/set/hash_map_set.ts)
* [Map Set](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/set/map_set.ts)
* [Set](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/set/set.ts)
* Stack
* [Linked List Stack](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/stack/linked_list_stack.ts)
* [Stack](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/stack/stack.ts)
* Test
* [Linked List Stack.Test](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/stack/test/linked_list_stack.test.ts)
* [Stack.Test](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/stack/test/stack.test.ts)
* Tree
* [Binary Search Tree](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/tree/binary_search_tree.ts)
* Test
* [Binary Search Tree.Test](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/data_structures/tree/test/binary_search_tree.test.ts)

## Dynamic Programming
* [Knapsack](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/dynamic_programming/knapsack.ts)

## Graph
* [Bellman Ford](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/graph/bellman_ford.ts)
* [Dijkstra](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/graph/dijkstra.ts)
* [Kruskal](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/graph/kruskal.ts)
* Test
* [Bellman Ford.Test](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/graph/test/bellman_ford.test.ts)
* [Dijkstra.Test](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/graph/test/dijkstra.test.ts)
* [Kruskal.Test](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/graph/test/kruskal.test.ts)

## Maths
* [Absolute Value](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/absolute_value.ts)
* [Aliquot Sum](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/aliquot_sum.ts)
* [Armstrong Number](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/armstrong_number.ts)
* [Binary Convert](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/binary_convert.ts)
* [Binomial Coefficient](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/binomial_coefficient.ts)
* [Calculate Mean](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/calculate_mean.ts)
* [Calculate Median](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/calculate_median.ts)
* [Degrees To Radians](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/degrees_to_radians.ts)
* [Digit Sum](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/digit_sum.ts)
* [Factorial](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/factorial.ts)
* [Factors](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/factors.ts)
* [Fibonacci](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/fibonacci.ts)
* [Find Min](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/find_min.ts)
* [Greatest Common Factor](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/greatest_common_factor.ts)
Expand All @@ -31,8 +86,13 @@
* [Is Odd](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/is_odd.ts)
* [Is Palindrome](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/is_palindrome.ts)
* [Is Square Free](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/is_square_free.ts)
* [Juggler Sequence](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/juggler_sequence.ts)
* [Lowest Common Multiple](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/lowest_common_multiple.ts)
* [Number Of Digits](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/number_of_digits.ts)
* [Pascals Triangle](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/pascals_triangle.ts)
* [Perfect Cube](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/perfect_cube.ts)
* [Perfect Square](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/perfect_square.ts)
* [Primes](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/primes.ts)
* [Pronic Number](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/pronic_number.ts)
* [Radians To Degrees](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/radians_to_degrees.ts)
* Series
Expand All @@ -41,6 +101,7 @@
* [Hexagonal Numbers.Test](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/series/test/hexagonal_numbers.test.ts)
* [Sieve Of Eratosthenes](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/sieve_of_eratosthenes.ts)
* [Signum](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/signum.ts)
* [Zellers Congruence](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/zellers_congruence.ts)

## Other
* [Parse Nested Brackets](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/other/parse_nested_brackets.ts)
Expand All @@ -58,4 +119,7 @@
* [Gnome Sort](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/sorts/gnome_sort.ts)
* [Insertion Sort](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/sorts/insertion_sort.ts)
* [Merge Sort](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/sorts/merge_sort.ts)
* [Quick Select](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/sorts/quick_select.ts)
* [Quick Sort](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/sorts/quick_sort.ts)
* [Selection Sort](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/sorts/selection_sort.ts)
* [Shell Sort](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/sorts/shell_sort.ts)
28 changes: 0 additions & 28 deletions maths/is_prime.ts

This file was deleted.

87 changes: 87 additions & 0 deletions maths/primes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,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;
};
19 changes: 0 additions & 19 deletions maths/test/is_prime.test.ts

This file was deleted.

59 changes: 59 additions & 0 deletions maths/test/primes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import {isPrime, primeGenerator, sieveOfEratosthenes} from "../primes";


describe(sieveOfEratosthenes, () => {
test.each([-1, 0, 1, 2.123, 1337.80085])(
"should throw an error when given an invalid limit=%d",
(invalidLimit) => {
expect(() => sieveOfEratosthenes(invalidLimit)).toThrow();
}
);
test.each([
[2, [2]],
[3, [2, 3]],
[4, [2, 3]],
[5, [2, 3, 5]],
[6, [2, 3, 5]],
[7, [2, 3, 5, 7]],
[8, [2, 3, 5, 7]],
[9, [2, 3, 5, 7]],
])(
"should return the expected list of primes for limit=%i",
(limit, expected) => {
expect(sieveOfEratosthenes(limit)).toEqual(expected);
}
);
});

describe(primeGenerator, () => {
it("should generate prime numbers", () => {
const primeGen = primeGenerator();
for (let i = 0; i < 100; i++) {
const prime = primeGen.next().value;

if (prime === undefined) {
throw new Error("prime generator returned undefined");
}

expect(isPrime(prime)).toBe(true);
}
});
});

describe("IsPrime", () => {
test.each([[1, false], [2, true], [3, true], [3 * 3, false], [13, true], [24, false]])(
"correct output for %i",
(nums, expected) => {
expect(isPrime(nums)).toBe(expected);
},
);

test.each([-890, -5.56, -7, 0.73, 4.2, NaN, -Infinity, Infinity])(
"should throw an error for non natural number %d",
(num) => {
expect(() => isPrime(num)).toThrowError(
"only natural numbers are supported",
);
},
);
});