Skip to content

Commit 99f9b25

Browse files
authored
Primes implements Sequence protocol, closes #29 (#41)
1 parent 896a1f0 commit 99f9b25

File tree

2 files changed

+27
-14
lines changed

2 files changed

+27
-14
lines changed

primes.py

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,21 @@
22
Several prime number functions
33
"""
44
from math import gcd, log
5-
from typing import Any, Iterable, List, Optional, Tuple, Sequence, Set
5+
from typing import Any, Iterator, Iterable, List, Optional, Tuple, Sequence, Set
66

77
from numpy import ones, zeros
88

99
from binary_search import binary_search, list_up_to
1010

11-
class Primes(List[int]):
11+
class Primes(Sequence[int]):
1212
"""
1313
List subclass that supports slicing and membership checking, automatically
1414
generating new primes when needed
1515
"""
1616

17+
def __init__(self) -> None:
18+
self.primes: List[int] = []
19+
1720
def __contains__(self, item: Any) -> bool:
1821
"""
1922
Check if a number is prime:
@@ -36,28 +39,38 @@ def __getitem__(self, key: Any) -> Any:
3639
return []
3740

3841
if key.start is not None and len(self)-1 < key.start:
39-
self += n_primes(key.start+1, list(self))[len(self):]
42+
self.primes += n_primes(key.start+1, self)[len(self):]
4043
if key.stop is not None and len(self) < key.stop:
41-
self += n_primes(key.stop, list(self))[len(self):]
44+
self.primes += n_primes(key.stop, self)[len(self):]
4245
elif isinstance(key, int):
4346
if len(self)-1 < key:
44-
self += n_primes(key+1, list(self))[len(self):]
47+
self.primes += n_primes(key+1, self)[len(self):]
4548
else:
4649
raise TypeError()
4750

48-
# pylint: disable=no-member
49-
return super().__getitem__(key)
50-
# pylint: enable=no-member
51+
return self.primes[key]
5152

5253
def index(self, prime: int, start: int = 0, stop: Optional[int] = None) -> int:
5354
"""
5455
The index of the prime
5556
"""
5657
if not self or self[-1] < prime:
57-
self += primes_up_to(prime, self)[len(self):]
58-
# pylint: disable=no-member
59-
return super().index(prime, start, stop or len(self))
60-
# pylint: enable=no-member
58+
self.primes += primes_up_to(prime, self)[len(self):]
59+
idx = binary_search(self.primes, prime, start, stop)
60+
if idx < 0:
61+
raise ValueError(f"{prime} is not prime")
62+
return idx
63+
64+
def __eq__(self, other: Any) -> Any:
65+
if isinstance(other, Primes):
66+
other = other.primes
67+
return self.primes == other
68+
69+
def __iter__(self) -> Iterator[int]:
70+
return iter(self.primes)
71+
72+
def __len__(self) -> int:
73+
return len(self.primes)
6174

6275
def _first_multiple_of(num: int, above: int) -> int:
6376
"""
@@ -421,7 +434,7 @@ def composites_up_to(limit: int, primes: Optional[Sequence[int]] = None) -> Sequ
421434
composites.extend(range(primes[-1]+1, limit+1))
422435
return composites
423436

424-
def next_prime(primes: List[int]) -> int:
437+
def next_prime(primes: Sequence[int]) -> int:
425438
"""
426439
Given primes, returns the next prime
427440

test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ def testIndex(self):
535535
self.assertEqual(self.primes.index(3), 1)
536536
self.assertEqual(self.primes.index(5), 2)
537537
self.assertEqual(self.primes.index(7), 3)
538-
self.assertRaisesRegex(ValueError, "4 is not in list", lambda p: p.index(4), self.primes)
538+
self.assertRaisesRegex(ValueError, "4 is not prime", lambda p: p.index(4), self.primes)
539539

540540
class TestSieves(unittest.TestCase):
541541
def testSieves(self):

0 commit comments

Comments
 (0)