Skip to content

Commit 9355359

Browse files
committed
Add SieveOfEratosthenes algorithm with tests
1 parent 07022c4 commit 9355359

File tree

2 files changed

+40
-79
lines changed

2 files changed

+40
-79
lines changed
Lines changed: 28 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,50 @@
11
package com.thealgorithms.maths;
22

3+
import java.util.ArrayList;
34
import java.util.Arrays;
5+
import java.util.List;
46

57
/**
6-
* @brief utility class implementing <a href="https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes">Sieve of Eratosthenes</a>
8+
* Utility class that provides the Sieve of Eratosthenes algorithm.
79
*/
810
public final class SieveOfEratosthenes {
11+
12+
/** Private constructor to prevent instantiation. */
913
private SieveOfEratosthenes() {
14+
throw new AssertionError("Cannot instantiate utility class.");
1015
}
1116

12-
private static void checkInput(int n) {
13-
if (n <= 0) {
14-
throw new IllegalArgumentException("n must be positive.");
17+
/**
18+
* Returns an array of all prime numbers less than or equal to {@code n}.
19+
*
20+
* @param n the upper bound (inclusive)
21+
* @return array of primes <= n (empty if n &lt; 2)
22+
*/
23+
public static int[] sieve(final int n) {
24+
if (n < 2) {
25+
return new int[0];
1526
}
16-
}
1727

18-
private static Type[] sievePrimesTill(int n) {
19-
checkInput(n);
20-
Type[] isPrimeArray = new Type[n + 1];
21-
Arrays.fill(isPrimeArray, Type.PRIME);
22-
isPrimeArray[0] = Type.NOT_PRIME;
23-
isPrimeArray[1] = Type.NOT_PRIME;
28+
boolean[] isPrime = new boolean[n + 1];
29+
Arrays.fill(isPrime, true);
30+
isPrime[0] = false;
31+
isPrime[1] = false;
2432

25-
double cap = Math.sqrt(n);
26-
for (int i = 2; i <= cap; i++) {
27-
if (isPrimeArray[i] == Type.PRIME) {
28-
for (int j = 2; i * j <= n; j++) {
29-
isPrimeArray[i * j] = Type.NOT_PRIME;
33+
for (int p = 2; p * p <= n; p++) {
34+
if (isPrime[p]) {
35+
for (int multiple = p * p; multiple <= n; multiple += p) {
36+
isPrime[multiple] = false;
3037
}
3138
}
3239
}
33-
return isPrimeArray;
34-
}
35-
36-
private static int countPrimes(Type[] isPrimeArray) {
37-
return (int) Arrays.stream(isPrimeArray).filter(element -> element == Type.PRIME).count();
38-
}
3940

40-
private static int[] extractPrimes(Type[] isPrimeArray) {
41-
int numberOfPrimes = countPrimes(isPrimeArray);
42-
int[] primes = new int[numberOfPrimes];
43-
int primeIndex = 0;
44-
for (int curNumber = 0; curNumber < isPrimeArray.length; ++curNumber) {
45-
if (isPrimeArray[curNumber] == Type.PRIME) {
46-
primes[primeIndex++] = curNumber;
41+
List<Integer> primes = new ArrayList<>();
42+
for (int i = 2; i <= n; i++) {
43+
if (isPrime[i]) {
44+
primes.add(i);
4745
}
4846
}
49-
return primes;
50-
}
51-
52-
/**
53-
* @brief finds all of the prime numbers up to the given upper (inclusive) limit
54-
* @param n upper (inclusive) limit
55-
* @exception IllegalArgumentException n is non-positive
56-
* @return the array of all primes up to the given number (inclusive)
57-
*/
58-
public static int[] findPrimesTill(int n) {
59-
return extractPrimes(sievePrimesTill(n));
60-
}
6147

62-
private enum Type {
63-
PRIME,
64-
NOT_PRIME,
48+
return primes.stream().mapToInt(Integer::intValue).toArray();
6549
}
6650
}
Lines changed: 12 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,23 @@
11
package com.thealgorithms.maths;
22

3-
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
4-
import static org.junit.jupiter.api.Assertions.assertThrows;
5-
3+
import org.junit.jupiter.api.Assertions;
64
import org.junit.jupiter.api.Test;
75

8-
class SieveOfEratosthenesTest {
9-
@Test
10-
public void testfFindPrimesTill1() {
11-
assertArrayEquals(new int[] {}, SieveOfEratosthenes.findPrimesTill(1));
12-
}
13-
14-
@Test
15-
public void testfFindPrimesTill2() {
16-
assertArrayEquals(new int[] {2}, SieveOfEratosthenes.findPrimesTill(2));
17-
}
18-
19-
@Test
20-
public void testfFindPrimesTill4() {
21-
var primesTill4 = new int[] {2, 3};
22-
assertArrayEquals(primesTill4, SieveOfEratosthenes.findPrimesTill(3));
23-
assertArrayEquals(primesTill4, SieveOfEratosthenes.findPrimesTill(4));
24-
}
25-
26-
@Test
27-
public void testfFindPrimesTill40() {
28-
var primesTill40 = new int[] {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};
29-
assertArrayEquals(primesTill40, SieveOfEratosthenes.findPrimesTill(37));
30-
assertArrayEquals(primesTill40, SieveOfEratosthenes.findPrimesTill(38));
31-
assertArrayEquals(primesTill40, SieveOfEratosthenes.findPrimesTill(39));
32-
assertArrayEquals(primesTill40, SieveOfEratosthenes.findPrimesTill(40));
33-
}
6+
/**
7+
* Unit tests for {@link SieveOfEratosthenes}.
8+
*/
9+
public final class SieveOfEratosthenesTest {
3410

3511
@Test
36-
public void testfFindPrimesTill240() {
37-
var primesTill240 = new int[] {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, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239};
38-
assertArrayEquals(primesTill240, SieveOfEratosthenes.findPrimesTill(239));
39-
assertArrayEquals(primesTill240, SieveOfEratosthenes.findPrimesTill(240));
12+
void testPrimesUpTo30() {
13+
int[] expected = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
14+
Assertions.assertArrayEquals(expected, SieveOfEratosthenes.sieve(30));
4015
}
4116

4217
@Test
43-
public void testFindPrimesTillThrowsExceptionForNonPositiveInput() {
44-
assertThrows(IllegalArgumentException.class, () -> SieveOfEratosthenes.findPrimesTill(0));
18+
void testLessThanTwo() {
19+
Assertions.assertArrayEquals(new int[0], SieveOfEratosthenes.sieve(1));
20+
Assertions.assertArrayEquals(new int[0], SieveOfEratosthenes.sieve(0));
21+
Assertions.assertArrayEquals(new int[0], SieveOfEratosthenes.sieve(-5));
4522
}
4623
}

0 commit comments

Comments
 (0)