@@ -844,6 +844,7 @@ which incur interpreter overhead.
844844 return next(islice(iterable, n, None), default)
845845
846846 def quantify(iterable, pred=bool):
847+ "Given a predicate that returns True or False, count the True results."
847848 "Count how many times the predicate is True"
848849 return sum(map(pred, iterable))
849850
@@ -1028,34 +1029,6 @@ The following recipes have a more mathematical flavor:
10281029 s = list(iterable)
10291030 return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
10301031
1031- def sieve(n):
1032- "Primes less than n."
1033- # sieve(30) --> 2 3 5 7 11 13 17 19 23 29
1034- if n > 2:
1035- yield 2
1036- start = 3
1037- data = bytearray((0, 1)) * (n // 2)
1038- limit = math.isqrt(n) + 1
1039- for p in iter_index(data, 1, start, limit):
1040- yield from iter_index(data, 1, start, p*p)
1041- data[p*p : n : p+p] = bytes(len(range(p*p, n, p+p)))
1042- start = p*p
1043- yield from iter_index(data, 1, start)
1044-
1045- def factor(n):
1046- "Prime factors of n."
1047- # factor(99) --> 3 3 11
1048- # factor(1_000_000_000_000_007) --> 47 59 360620266859
1049- # factor(1_000_000_000_000_403) --> 1000000000000403
1050- for prime in sieve(math.isqrt(n) + 1):
1051- while not n % prime:
1052- yield prime
1053- n //= prime
1054- if n == 1:
1055- return
1056- if n > 1:
1057- yield n
1058-
10591032 def sum_of_squares(it):
10601033 "Add up the squares of the input values."
10611034 # sum_of_squares([10, 20, 30]) -> 1400
@@ -1073,14 +1046,21 @@ The following recipes have a more mathematical flavor:
10731046 return batched(starmap(math.sumprod, product(m1, transpose(m2))), n)
10741047
10751048 def convolve(signal, kernel):
1076- """Linear convolution of two iterables.
1049+ """Discrete linear convolution of two iterables.
1050+
1051+ The kernel is fully consumed before the calculations begin.
1052+ The signal is consumed lazily and can be infinite.
1053+
1054+ Convolutions are mathematically commutative.
1055+ If the signal and kernel are swapped,
1056+ the output will be the same.
10771057
10781058 Article: https://betterexplained.com/articles/intuitive-convolution/
10791059 Video: https://www.youtube.com/watch?v=KuXjwB4LzSA
10801060 """
10811061 # convolve(data, [0.25, 0.25, 0.25, 0.25]) --> Moving average (blur)
1082- # convolve(data, [1, -1 ]) --> 1st finite difference (1st derivative)
1083- # convolve(data, [1, -2, 1]) --> 2nd finite difference (2nd derivative)
1062+ # convolve(data, [1/2, 0, -1/2 ]) --> 1st derivative estimate
1063+ # convolve(data, [1, -2, 1]) --> 2nd derivative estimate
10841064 kernel = tuple(kernel)[::-1]
10851065 n = len(kernel)
10861066 padded_signal = chain(repeat(0, n-1), signal, repeat(0, n-1))
@@ -1104,8 +1084,8 @@ The following recipes have a more mathematical flavor:
11041084 # Evaluate x³ -4x² -17x + 60 at x = 2.5
11051085 # polynomial_eval([1, -4, -17, 60], x=2.5) --> 8.125
11061086 n = len(coefficients)
1107- if n == 0 :
1108- return x * 0 # coerce zero to the type of x
1087+ if not n :
1088+ return type(x)(0)
11091089 powers = map(pow, repeat(x), reversed(range(n)))
11101090 return math.sumprod(coefficients, powers)
11111091
@@ -1120,6 +1100,34 @@ The following recipes have a more mathematical flavor:
11201100 powers = reversed(range(1, n))
11211101 return list(map(operator.mul, coefficients, powers))
11221102
1103+ def sieve(n):
1104+ "Primes less than n."
1105+ # sieve(30) --> 2 3 5 7 11 13 17 19 23 29
1106+ if n > 2:
1107+ yield 2
1108+ start = 3
1109+ data = bytearray((0, 1)) * (n // 2)
1110+ limit = math.isqrt(n) + 1
1111+ for p in iter_index(data, 1, start, limit):
1112+ yield from iter_index(data, 1, start, p*p)
1113+ data[p*p : n : p+p] = bytes(len(range(p*p, n, p+p)))
1114+ start = p*p
1115+ yield from iter_index(data, 1, start)
1116+
1117+ def factor(n):
1118+ "Prime factors of n."
1119+ # factor(99) --> 3 3 11
1120+ # factor(1_000_000_000_000_007) --> 47 59 360620266859
1121+ # factor(1_000_000_000_000_403) --> 1000000000000403
1122+ for prime in sieve(math.isqrt(n) + 1):
1123+ while not n % prime:
1124+ yield prime
1125+ n //= prime
1126+ if n == 1:
1127+ return
1128+ if n > 1:
1129+ yield n
1130+
11231131 def nth_combination(iterable, r, index):
11241132 "Equivalent to list(combinations(iterable, r))[index]"
11251133 pool = tuple(iterable)
@@ -1295,7 +1303,7 @@ The following recipes have a more mathematical flavor:
12951303 >>> polynomial_eval([], Fraction(2 , 3 ))
12961304 Fraction(0, 1)
12971305 >>> polynomial_eval([], Decimal(' 1.75' ))
1298- Decimal('0.00 ')
1306+ Decimal('0')
12991307 >>> polynomial_eval([11 ], 7 ) == 11
13001308 True
13011309 >>> polynomial_eval([11 , 2 ], 7 ) == 11 * 7 + 2
0 commit comments