@@ -844,6 +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
+ "Given a predicate that returns True or False, count the True results."
847
848
"Count how many times the predicate is True"
848
849
return sum(map(pred, iterable))
849
850
@@ -1028,34 +1029,6 @@ The following recipes have a more mathematical flavor:
1028
1029
s = list(iterable)
1029
1030
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
1030
1031
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
-
1059
1032
def sum_of_squares(it):
1060
1033
"Add up the squares of the input values."
1061
1034
# sum_of_squares([10, 20, 30]) -> 1400
@@ -1073,14 +1046,21 @@ The following recipes have a more mathematical flavor:
1073
1046
return batched(starmap(math.sumprod, product(m1, transpose(m2))), n)
1074
1047
1075
1048
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.
1077
1057
1078
1058
Article: https://betterexplained.com/articles/intuitive-convolution/
1079
1059
Video: https://www.youtube.com/watch?v=KuXjwB4LzSA
1080
1060
"""
1081
1061
# 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
1084
1064
kernel = tuple(kernel)[::-1]
1085
1065
n = len(kernel)
1086
1066
padded_signal = chain(repeat(0, n-1), signal, repeat(0, n-1))
@@ -1104,8 +1084,8 @@ The following recipes have a more mathematical flavor:
1104
1084
# Evaluate x³ -4x² -17x + 60 at x = 2.5
1105
1085
# polynomial_eval([1, -4, -17, 60], x=2.5) --> 8.125
1106
1086
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)
1109
1089
powers = map(pow, repeat(x), reversed(range(n)))
1110
1090
return math.sumprod(coefficients, powers)
1111
1091
@@ -1120,6 +1100,34 @@ The following recipes have a more mathematical flavor:
1120
1100
powers = reversed(range(1, n))
1121
1101
return list(map(operator.mul, coefficients, powers))
1122
1102
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
+
1123
1131
def nth_combination(iterable, r, index):
1124
1132
"Equivalent to list(combinations(iterable, r))[index]"
1125
1133
pool = tuple(iterable)
@@ -1295,7 +1303,7 @@ The following recipes have a more mathematical flavor:
1295
1303
>>> polynomial_eval([], Fraction(2 , 3 ))
1296
1304
Fraction(0, 1)
1297
1305
>>> polynomial_eval([], Decimal(' 1.75' ))
1298
- Decimal('0.00 ')
1306
+ Decimal('0')
1299
1307
>>> polynomial_eval([11 ], 7 ) == 11
1300
1308
True
1301
1309
>>> polynomial_eval([11 , 2 ], 7 ) == 11 * 7 + 2
0 commit comments