Skip to content
Closed
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
54 changes: 16 additions & 38 deletions maths/prime_numbers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import math
from typing import Generator

"""
Naive implementation of finding primes by checking if each number
is divisible by 2 or any odd number up to its root.

For a fast implementation see Sieve of Eratosthenes.
"""

Comment on lines +4 to +10
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok to keep an explanation, but state that there are two impls, and you can compre both.


def slow_primes(max: int) -> Generator[int, None, None]:
"""
Expand All @@ -9,8 +16,8 @@ def slow_primes(max: int) -> Generator[int, None, None]:
[]
>>> list(slow_primes(-1))
[]
>>> list(slow_primes(-10))
[]
>>> list(slow_primes(2))
[2]
>>> list(slow_primes(25))
[2, 3, 5, 7, 11, 13, 17, 19, 23]
>>> list(slow_primes(11))
Expand All @@ -22,49 +29,20 @@ def slow_primes(max: int) -> Generator[int, None, None]:
"""
numbers: Generator = (i for i in range(1, (max + 1)))
for i in (n for n in numbers if n > 1):
for j in range(2, i):
if (i % j) == 0:
break
else:
yield i
Comment on lines -26 to -29
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove these brackets



def primes(max: int) -> Generator[int, None, None]:
"""
Return a list of all primes numbers up to max.
>>> list(primes(0))
[]
>>> list(primes(-1))
[]
>>> list(primes(-10))
[]
>>> list(primes(25))
[2, 3, 5, 7, 11, 13, 17, 19, 23]
>>> list(primes(11))
[2, 3, 5, 7, 11]
>>> list(primes(33))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31]
>>> list(primes(10000))[-1]
9973
"""
Comment on lines -35 to -49
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and keep the tests?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests dont make sense since we removed one of the functions, it just compared the two timings

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest we keep this referential implementation. Please see #1984, #1519.

numbers: Generator = (i for i in range(1, (max + 1)))
for i in (n for n in numbers if n > 1):
if i % 2 == 0:
if i == 2:
yield 2
continue
# only need to check for factors up to sqrt(i)
bound = int(math.sqrt(i)) + 1
for j in range(2, bound):
if (i % j) == 0:
for j in range(3, bound, 2):
if i % j == 0:
break
else:
yield i


if __name__ == "__main__":
number = int(input("Calculate primes up to:\n>> ").strip())
for ret in primes(number):
for ret in slow_primes(number):
print(ret)

# Let's benchmark them side-by-side...
from timeit import timeit

print(timeit("slow_primes(1_000_000)", setup="from __main__ import slow_primes"))
print(timeit("primes(1_000_000)", setup="from __main__ import primes"))