return next(islice(iterable, n, None), default)
def quantify(iterable, pred=bool):
- "Count how many times the predicate is True"
+ "Given a predicate that returns True or False, count the True results."
return sum(map(pred, iterable))
def all_equal(iterable):
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
- def sieve(n):
- "Primes less than n."
- # sieve(30) --> 2 3 5 7 11 13 17 19 23 29
- if n > 2:
- yield 2
- start = 3
- data = bytearray((0, 1)) * (n // 2)
- limit = math.isqrt(n) + 1
- for p in iter_index(data, 1, start, limit):
- yield from iter_index(data, 1, start, p*p)
- data[p*p : n : p+p] = bytes(len(range(p*p, n, p+p)))
- start = p*p
- yield from iter_index(data, 1, start)
-
- def factor(n):
- "Prime factors of n."
- # factor(99) --> 3 3 11
- # factor(1_000_000_000_000_007) --> 47 59 360620266859
- # factor(1_000_000_000_000_403) --> 1000000000000403
- for prime in sieve(math.isqrt(n) + 1):
- while True:
- if n % prime:
- break
- yield prime
- n //= prime
- if n == 1:
- return
- if n > 1:
- yield n
-
def sum_of_squares(it):
"Add up the squares of the input values."
# sum_of_squares([10, 20, 30]) -> 1400
return batched(starmap(math.sumprod, product(m1, transpose(m2))), n)
def convolve(signal, kernel):
- """Linear convolution of two iterables.
+ """Discrete linear convolution of two iterables.
+
+ The kernel is fully consumed before the calculations begin.
+ The signal is consumed lazily and can be infinite.
+
+ Convolutions are mathematically commutative.
+ If the signal and kernel are swapped,
+ the output will be the same.
Article: https://betterexplained.com/articles/intuitive-convolution/
Video: https://www.youtube.com/watch?v=KuXjwB4LzSA
"""
# convolve(data, [0.25, 0.25, 0.25, 0.25]) --> Moving average (blur)
- # convolve(data, [1, -1]) --> 1st finite difference (1st derivative)
- # convolve(data, [1, -2, 1]) --> 2nd finite difference (2nd derivative)
+ # convolve(data, [1/2, 0, -1/2]) --> 1st derivative estimate
+ # convolve(data, [1, -2, 1]) --> 2nd derivative estimate
kernel = tuple(kernel)[::-1]
n = len(kernel)
padded_signal = chain(repeat(0, n-1), signal, repeat(0, n-1))
# Evaluate x³ -4x² -17x + 60 at x = 2.5
# polynomial_eval([1, -4, -17, 60], x=2.5) --> 8.125
n = len(coefficients)
- if n == 0:
- return x * 0 # coerce zero to the type of x
+ if not n:
+ return type(x)(0)
powers = map(pow, repeat(x), reversed(range(n)))
return math.sumprod(coefficients, powers)
powers = reversed(range(1, n))
return list(map(operator.mul, coefficients, powers))
+ def sieve(n):
+ "Primes less than n."
+ # sieve(30) --> 2 3 5 7 11 13 17 19 23 29
+ if n > 2:
+ yield 2
+ start = 3
+ data = bytearray((0, 1)) * (n // 2)
+ limit = math.isqrt(n) + 1
+ for p in iter_index(data, 1, start, limit):
+ yield from iter_index(data, 1, start, p*p)
+ data[p*p : n : p+p] = bytes(len(range(p*p, n, p+p)))
+ start = p*p
+ yield from iter_index(data, 1, start)
+
+ def factor(n):
+ "Prime factors of n."
+ # factor(99) --> 3 3 11
+ # factor(1_000_000_000_000_007) --> 47 59 360620266859
+ # factor(1_000_000_000_000_403) --> 1000000000000403
+ for prime in sieve(math.isqrt(n) + 1):
+ while True:
+ if n % prime:
+ break
+ yield prime
+ n //= prime
+ if n == 1:
+ return
+ if n > 1:
+ yield n
+
def nth_combination(iterable, r, index):
"Equivalent to list(combinations(iterable, r))[index]"
pool = tuple(iterable)
>>> polynomial_eval([], Fraction(2, 3))
Fraction(0, 1)
>>> polynomial_eval([], Decimal('1.75'))
- Decimal('0.00')
+ Decimal('0')
>>> polynomial_eval([11], 7) == 11
True
>>> polynomial_eval([11, 2], 7) == 11 * 7 + 2