[Python-checkins] Faster sieve() recipe (#98287)

rhettinger webhook-mailer at python.org
Sat Oct 15 13:44:07 EDT 2022


https://github.com/python/cpython/commit/f4370318d67f1f2f686c1c3a4b217ccc461d31e5
commit: f4370318d67f1f2f686c1c3a4b217ccc461d31e5
branch: main
author: Raymond Hettinger <rhettinger at users.noreply.github.com>
committer: rhettinger <rhettinger at users.noreply.github.com>
date: 2022-10-15T12:43:58-05:00
summary:

Faster sieve() recipe (#98287)

files:
M Doc/library/itertools.rst

diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst
index 6571114ef311..056b0788a4d8 100644
--- a/Doc/library/itertools.rst
+++ b/Doc/library/itertools.rst
@@ -809,15 +809,25 @@ which incur interpreter overhead.
            for k in range(len(roots) + 1)
        ]
 
+   def iter_index(seq, value, start=0):
+       "Return indices where a value occurs in a sequence."
+       # iter_index('AABCADEAF', 'A') --> 0 1 4 7
+       i = start - 1
+       try:
+           while True:
+               yield (i := seq.index(value, i+1))
+       except ValueError:
+           pass
+
    def sieve(n):
-      "Primes less than n"
-      # sieve(30) --> 2 3 5 7 11 13 17 19 23 29
-      data = bytearray([1]) * n
-      data[:2] = 0, 0
-      limit = math.isqrt(n) + 1
-      for p in compress(range(limit), data):
-         data[p+p : n : p] = bytearray(len(range(p+p, n, p)))
-      return compress(count(), data)
+       "Primes less than n"
+       # sieve(30) --> 2 3 5 7 11 13 17 19 23 29
+       data = bytearray([1]) * n
+       data[:2] = 0, 0
+       limit = math.isqrt(n) + 1
+       for p in compress(range(limit), data):
+           data[p*p : n : p] = bytearray(len(range(p*p, n, p)))
+       return iter_index(data, 1)
 
    def flatten(list_of_lists):
        "Flatten one level of nesting"
@@ -1170,6 +1180,15 @@ which incur interpreter overhead.
     >>> all(factored(x) == expanded(x) for x in range(-10, 11))
     True
 
+    >>> list(iter_index('AABCADEAF', 'A'))
+    [0, 1, 4, 7]
+    >>> list(iter_index('AABCADEAF', 'B'))
+    [2]
+    >>> list(iter_index('AABCADEAF', 'X'))
+    []
+    >>> list(iter_index('', 'X'))
+    []
+
     >>> list(sieve(30))
     [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
     >>> small_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]



More information about the Python-checkins mailing list