@@ -844,7 +844,7 @@ which incur interpreter overhead.
844
844
return next(islice(iterable, n, None), default)
845
845
846
846
def quantify(iterable, pred=bool):
847
- "Count how many times the predicate is True"
847
+ "Given a predicate that returns True or False, count the True results. "
848
848
return sum(map(pred, iterable))
849
849
850
850
def all_equal(iterable):
@@ -1028,36 +1028,6 @@ The following recipes have a more mathematical flavor:
1028
1028
s = list(iterable)
1029
1029
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
1030
1030
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 True:
1052
- if n % prime:
1053
- break
1054
- yield prime
1055
- n //= prime
1056
- if n == 1:
1057
- return
1058
- if n > 1:
1059
- yield n
1060
-
1061
1031
def sum_of_squares(it):
1062
1032
"Add up the squares of the input values."
1063
1033
# sum_of_squares([10, 20, 30]) -> 1400
@@ -1075,14 +1045,21 @@ The following recipes have a more mathematical flavor:
1075
1045
return batched(starmap(math.sumprod, product(m1, transpose(m2))), n)
1076
1046
1077
1047
def convolve(signal, kernel):
1078
- """Linear convolution of two iterables.
1048
+ """Discrete linear convolution of two iterables.
1049
+
1050
+ The kernel is fully consumed before the calculations begin.
1051
+ The signal is consumed lazily and can be infinite.
1052
+
1053
+ Convolutions are mathematically commutative.
1054
+ If the signal and kernel are swapped,
1055
+ the output will be the same.
1079
1056
1080
1057
Article: https://betterexplained.com/articles/intuitive-convolution/
1081
1058
Video: https://www.youtube.com/watch?v=KuXjwB4LzSA
1082
1059
"""
1083
1060
# convolve(data, [0.25, 0.25, 0.25, 0.25]) --> Moving average (blur)
1084
- # convolve(data, [1, -1 ]) --> 1st finite difference (1st derivative)
1085
- # convolve(data, [1, -2, 1]) --> 2nd finite difference (2nd derivative)
1061
+ # convolve(data, [1/2, 0, -1/2 ]) --> 1st derivative estimate
1062
+ # convolve(data, [1, -2, 1]) --> 2nd derivative estimate
1086
1063
kernel = tuple(kernel)[::-1]
1087
1064
n = len(kernel)
1088
1065
padded_signal = chain(repeat(0, n-1), signal, repeat(0, n-1))
@@ -1106,8 +1083,8 @@ The following recipes have a more mathematical flavor:
1106
1083
# Evaluate x³ -4x² -17x + 60 at x = 2.5
1107
1084
# polynomial_eval([1, -4, -17, 60], x=2.5) --> 8.125
1108
1085
n = len(coefficients)
1109
- if n == 0 :
1110
- return x * 0 # coerce zero to the type of x
1086
+ if not n :
1087
+ return type(x)(0)
1111
1088
powers = map(pow, repeat(x), reversed(range(n)))
1112
1089
return math.sumprod(coefficients, powers)
1113
1090
@@ -1122,6 +1099,36 @@ The following recipes have a more mathematical flavor:
1122
1099
powers = reversed(range(1, n))
1123
1100
return list(map(operator.mul, coefficients, powers))
1124
1101
1102
+ def sieve(n):
1103
+ "Primes less than n."
1104
+ # sieve(30) --> 2 3 5 7 11 13 17 19 23 29
1105
+ if n > 2:
1106
+ yield 2
1107
+ start = 3
1108
+ data = bytearray((0, 1)) * (n // 2)
1109
+ limit = math.isqrt(n) + 1
1110
+ for p in iter_index(data, 1, start, limit):
1111
+ yield from iter_index(data, 1, start, p*p)
1112
+ data[p*p : n : p+p] = bytes(len(range(p*p, n, p+p)))
1113
+ start = p*p
1114
+ yield from iter_index(data, 1, start)
1115
+
1116
+ def factor(n):
1117
+ "Prime factors of n."
1118
+ # factor(99) --> 3 3 11
1119
+ # factor(1_000_000_000_000_007) --> 47 59 360620266859
1120
+ # factor(1_000_000_000_000_403) --> 1000000000000403
1121
+ for prime in sieve(math.isqrt(n) + 1):
1122
+ while True:
1123
+ if n % prime:
1124
+ break
1125
+ yield prime
1126
+ n //= prime
1127
+ if n == 1:
1128
+ return
1129
+ if n > 1:
1130
+ yield n
1131
+
1125
1132
def nth_combination(iterable, r, index):
1126
1133
"Equivalent to list(combinations(iterable, r))[index]"
1127
1134
pool = tuple(iterable)
@@ -1297,7 +1304,7 @@ The following recipes have a more mathematical flavor:
1297
1304
>>> polynomial_eval([], Fraction(2 , 3 ))
1298
1305
Fraction(0, 1)
1299
1306
>>> polynomial_eval([], Decimal(' 1.75' ))
1300
- Decimal('0.00 ')
1307
+ Decimal('0')
1301
1308
>>> polynomial_eval([11 ], 7 ) == 11
1302
1309
True
1303
1310
>>> polynomial_eval([11 , 2 ], 7 ) == 11 * 7 + 2
0 commit comments