Files
projecteuler/util/python/sieve.py
2024-02-07 15:06:50 +01:00

79 lines
2.4 KiB
Python

from math import sqrt, floor
class sieve:
def __init__(self):
self.sieve = [False]
self._length = 1
self._target = 1
def run(self, n):
self._target = n
self._elongate()
def get(self, n):
if n > self._length:
self.run(n)
return self.sieve[n-1]
def _elongate(self):
length = self._length
target = self._target
diff = target - length
if diff > 0:
self.sieve += [True for _ in range(diff)]
for i in range(floor(sqrt(target))):
if self.sieve[i]:
_floor = length//(i+1)
_ceil = target//(i+1)
for j in range(_floor, _ceil):
actual = (i+1)*(j+1)-1
if actual > i+1:
self.sieve[actual] = False
self._length = target
class extended_sieve:
def __init__(self):
self.sieve = [[False, 1, []]]
self._length = 1
self._target = 1
self.prerun_step = 1000
def run(self, n):
self._target = n
self._elongate()
def get(self, n):
if n > self._length:
self.run(n+self.prerun_step)
prime_decomp = {}
for e in self.sieve[n-1][2]:
if e in list(prime_decomp.keys()):
prime_decomp[e] += 1
else:
prime_decomp[e] = 1
return [self.sieve[n-1][0], prime_decomp]
def _elongate(self):
length = self._length
target = self._target
diff = target - length
if diff > 0:
self.sieve += [[True, length+i+1, []] for i in range(diff)]
for i in range(target):
if self.sieve[i][0]:
if i+1 > length:
self.sieve[i][2] += [i+1]
_floor = length//(i+1)
_ceil = target//(i+1)
for j in range(_floor, _ceil):
actual = (i+1)*(j+1)-1
if actual > i+1:
old_entry = self.sieve[actual]
self.sieve[actual] = [False, old_entry[1]//(i+1), old_entry[2]+[i+1]]
elif self.sieve[i][1] != 1:
old_entry = self.sieve[i]
self.sieve[i] = [False, 1, old_entry[2]+self.sieve[old_entry[1]-1][2]]
self._length = target