Skip to content

Commit 63153b6

Browse files
Added segmented sieve for generating prime number in a given range, providing more memory efficiency
1 parent 7a797e1 commit 63153b6

File tree

1 file changed

+83
-15
lines changed

1 file changed

+83
-15
lines changed

Prime/code.py

Lines changed: 83 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,55 @@
1-
def SieveOfEratosthenes(range_to):
1+
import time
2+
from math import sqrt, ceil
23

3-
# creating a boolean array first
4+
5+
def segmented_sieve(range_from, range_to):
6+
"""
7+
Segmented sieve helps in providing a efficient way in terms of
8+
memory to find the prime numbers in a given range.
9+
10+
Space complexity: O(l)
11+
Time complexity: O(l log(logl))
12+
13+
l = range_to - range_from
14+
"""
15+
16+
# if the range starts from 1, incerement it.
17+
if range_from == 1:
18+
range_from += 1
19+
20+
# initialize a boolean list of size l, with True.
21+
primes_range = [True for _ in range(range_to - range_from + 1)]
22+
23+
# generate primes upto sqrt(range_to) using SieveOfEratosthenes.
24+
primes = sieve_eratosthenes(ceil(sqrt(range_to)))
25+
26+
# for every prime, all its multiples will not be prime
27+
for prime in primes:
28+
prime_multiple = max(range_from // prime, 2) * prime
29+
30+
# cross off all the multiple of the prime number.
31+
for i in range(prime_multiple, range_to + 1, prime):
32+
if i >= range_from:
33+
primes_range[i - range_from] = False
34+
35+
# return a list of prime numbers from range_from to range_to
36+
return [range_from + i for i, prime in enumerate(primes_range) if prime]
37+
38+
39+
def sieve_eratosthenes(range_to):
40+
"""
41+
A Very efficient way to generate all prime numbers upto a number.
42+
43+
Space complexity: O(n)
44+
Time complexity: O(n * log(logn))
45+
46+
n = the number upto which prime numbers are to be generated.
47+
"""
48+
49+
# creating a boolean list first
450
prime = [True for i in range(range_to + 1)]
551
p = 2
6-
while (p * p <= range_to):
52+
while (p * p <= range_to):
753

854
# If prime[p] is not changed, then it is a prime
955
if (prime[p] == True):
@@ -14,27 +60,49 @@ def SieveOfEratosthenes(range_to):
1460

1561
p += 1
1662

17-
print([p for p in range(2, range_to) if prime[p]])
63+
# return the list of primes
64+
return [p for p in range(2, range_to + 1) if prime[p]]
1865

1966

2067
def is_prime(num):
21-
for i in range(2, int(num / 2) + 1):
22-
if num % i == 0:
23-
return False
24-
return True
68+
"""
69+
Returns true is the number is prime.
70+
71+
To check if a number is prime, we need to check
72+
all its divisors upto only sqrt(number).
73+
74+
Reference: https://stackoverflow.com/a/5811176/7213370
75+
"""
76+
77+
# corner case. 1 is not a prime
78+
if num == 1:
79+
return False
80+
81+
# check if for a divisor upto sqrt(number)
82+
i = 2
83+
while i * i <= num:
84+
if num % i == 0:
85+
return False
86+
i += 1
87+
88+
return True
2589

2690

2791
def prime(range_from, range_to):
28-
allList = [num for num in range(range_from, range_to + 1) if is_prime(num)]
92+
"""
93+
Brute Force. O(l * sqrt(num)) [l = range_to - range_from]
94+
95+
Returns list of primes in the given range, by checking
96+
if the number is a prime or not.
97+
"""
98+
return [num for num in range(range_from, range_to + 1) if is_prime(num)]
99+
29100

30-
print("Prime List Between", range_from, "and", range_to, "is")
31-
print(allList)
32-
33-
34101
if __name__ == "__main__":
35102
print("Enter the range of number")
36103
range_from = int(input("From: "))
37104
range_to = int(input("To: "))
38105

39-
prime(range_from, range_to)
40-
SieveOfEratosthenes(range_to)
106+
print("Brute force:", prime(range_from, range_to), end="\n\n")
107+
print("Sieve of Eratosthenes:", sieve_eratosthenes(range_to), end="\n\n")
108+
print("Segmented Sieve:", segmented_sieve(range_from, range_to))

0 commit comments

Comments
 (0)