Skip to content

Instantly share code, notes, and snippets.

@arseniiv
Created August 30, 2025 14:33
Show Gist options
  • Select an option

  • Save arseniiv/1074cd20943981e5c7ae49fccd2fd47e to your computer and use it in GitHub Desktop.

Select an option

Save arseniiv/1074cd20943981e5c7ae49fccd2fd47e to your computer and use it in GitHub Desktop.
Eratosthenes prime sieve using iterators
from __future__ import annotations
from collections import deque
from itertools import count, cycle, islice
from typing import Final, Iterator
from time import perf_counter
def sieve() -> Iterator[int]:
"""
A slightly improved Eratosthenes prime sieve, implemented using iterators.
Cycles start on squares of primes because adding them earlier is unnecessary.
"""
yield 2
yield 3
cycles: list[Iterator[int]] = []
schedule_cycles = deque([(9, 3)])
for n in count(5, 2):
if n == schedule_cycles[0][0]:
cycles.append(cycle(range(schedule_cycles[0][1])))
schedule_cycles.popleft()
is_prime = True
for c in cycles:
if next(c) == 0:
is_prime = False
if is_prime:
yield n
schedule_cycles.append((n * n, n))
def main() -> None:
COUNT: Final = 100_000
t1 = perf_counter()
primes = list(islice(sieve(), COUNT))
t2 = perf_counter()
print(f'Computed {COUNT:_} primes in {t2 - t1 :.5f} sec.\nFirst 50:')
print(primes[:50])
print(f'Last 10:\n{primes[-10:]}\nTesting first 5000 numbers for primality...')
all_prime = True
for n, pn in enumerate(primes):
if n == 5000:
break
if not all(pn % p for p in primes[:n]):
all_prime = False
print(f'ERROR! A composite number {pn} is a multiple of an earlier listed number!')
break
if all_prime:
print('No number is a multiple of an earlier one! As intended.')
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment