1"""Imported from the recipes section of the itertools documentation.
2
3All functions taken from the recipes section of the itertools library docs
4[1]_.
5Some backward-compatible usability improvements have been made.
6
7.. [1] http://docs.python.org/library/itertools.html#recipes
8
9"""
10
11import random
12
13from bisect import bisect_left, insort
14from collections import deque
15from contextlib import suppress
16from dataclasses import dataclass
17from functools import lru_cache, reduce
18from heapq import heappush, heappushpop
19from itertools import (
20 accumulate,
21 chain,
22 combinations,
23 compress,
24 count,
25 cycle,
26 filterfalse,
27 groupby,
28 islice,
29 pairwise as itertools_pairwise,
30 product,
31 repeat,
32 starmap,
33 takewhile,
34 tee,
35 zip_longest,
36)
37from math import prod, comb, isqrt, gcd
38from operator import mul, getitem, index as _index, is_, itemgetter, truediv
39from random import randrange, sample, choice, shuffle
40from sys import hexversion
41
42__all__ = [
43 'Stats',
44 'all_equal',
45 'batched',
46 'before_and_after',
47 'consume',
48 'convolve',
49 'dotproduct',
50 'first_true',
51 'factor',
52 'flatten',
53 'grouper',
54 'is_prime',
55 'iter_except',
56 'iter_index',
57 'loops',
58 'matmul',
59 'multinomial',
60 'ncycles',
61 'nth',
62 'nth_combination',
63 'padnone',
64 'pad_none',
65 'pairwise',
66 'partition',
67 'polynomial_eval',
68 'polynomial_from_roots',
69 'polynomial_derivative',
70 'powerset',
71 'prepend',
72 'quantify',
73 'reshape',
74 'random_combination_with_replacement',
75 'random_combination',
76 'random_derangement',
77 'random_permutation',
78 'random_product',
79 'repeatfunc',
80 'roundrobin',
81 'running_max',
82 'running_mean',
83 'running_median',
84 'running_min',
85 'running_statistics',
86 'sieve',
87 'sliding_window',
88 'subslices',
89 'sum_of_squares',
90 'tabulate',
91 'tail',
92 'take',
93 'totient',
94 'transpose',
95 'triplewise',
96 'unique',
97 'unique_everseen',
98 'unique_justseen',
99]
100
101_marker = object()
102
103
104# heapq max-heap functions are available for Python 3.14+
105try:
106 from heapq import heappush_max, heappushpop_max
107except ImportError: # pragma: no cover
108 _max_heap_available = False
109else: # pragma: no cover
110 _max_heap_available = True
111
112
113def take(n, iterable):
114 """Return first *n* items of the *iterable* as a list.
115
116 >>> take(3, range(10))
117 [0, 1, 2]
118
119 If there are fewer than *n* items in the iterable, all of them are
120 returned.
121
122 >>> take(10, range(3))
123 [0, 1, 2]
124
125 """
126 return list(islice(iterable, n))
127
128
129def tabulate(function, start=0):
130 """Return an iterator over the results of ``func(start)``,
131 ``func(start + 1)``, ``func(start + 2)``...
132
133 *func* should be a function that accepts one integer argument.
134
135 If *start* is not specified it defaults to 0. It will be incremented each
136 time the iterator is advanced.
137
138 >>> square = lambda x: x ** 2
139 >>> iterator = tabulate(square, -3)
140 >>> take(4, iterator)
141 [9, 4, 1, 0]
142
143 """
144 return map(function, count(start))
145
146
147def tail(n, iterable):
148 """Return an iterator over the last *n* items of *iterable*.
149
150 >>> t = tail(3, 'ABCDEFG')
151 >>> list(t)
152 ['E', 'F', 'G']
153
154 """
155 try:
156 size = len(iterable)
157 except TypeError:
158 return iter(deque(iterable, maxlen=n))
159 else:
160 return islice(iterable, max(0, size - n), None)
161
162
163def consume(iterator, n=None):
164 """Advance *iterable* by *n* steps. If *n* is ``None``, consume it
165 entirely.
166
167 Efficiently exhausts an iterator without returning values. Defaults to
168 consuming the whole iterator, but an optional second argument may be
169 provided to limit consumption.
170
171 >>> i = (x for x in range(10))
172 >>> next(i)
173 0
174 >>> consume(i, 3)
175 >>> next(i)
176 4
177 >>> consume(i)
178 >>> next(i)
179 Traceback (most recent call last):
180 File "<stdin>", line 1, in <module>
181 StopIteration
182
183 If the iterator has fewer items remaining than the provided limit, the
184 whole iterator will be consumed.
185
186 >>> i = (x for x in range(3))
187 >>> consume(i, 5)
188 >>> next(i)
189 Traceback (most recent call last):
190 File "<stdin>", line 1, in <module>
191 StopIteration
192
193 """
194 # Use functions that consume iterators at C speed.
195 if n is None:
196 # feed the entire iterator into a zero-length deque
197 deque(iterator, maxlen=0)
198 else:
199 # advance to the empty slice starting at position n
200 next(islice(iterator, n, n), None)
201
202
203def nth(iterable, n, default=None):
204 """Returns the nth item or a default value.
205
206 >>> l = range(10)
207 >>> nth(l, 3)
208 3
209 >>> nth(l, 20, "zebra")
210 'zebra'
211
212 """
213 return next(islice(iterable, n, None), default)
214
215
216def all_equal(iterable, key=None):
217 """
218 Returns ``True`` if all the elements are equal to each other.
219
220 >>> all_equal('aaaa')
221 True
222 >>> all_equal('aaab')
223 False
224
225 A function that accepts a single argument and returns a transformed version
226 of each input item can be specified with *key*:
227
228 >>> all_equal('AaaA', key=str.casefold)
229 True
230 >>> all_equal([1, 2, 3], key=lambda x: x < 10)
231 True
232
233 """
234 iterator = groupby(iterable, key)
235 for first in iterator:
236 for second in iterator:
237 return False
238 return True
239 return True
240
241
242def quantify(iterable, pred=bool):
243 """Return the how many times the predicate is true.
244
245 >>> quantify([True, False, True])
246 2
247
248 """
249 return sum(map(pred, iterable))
250
251
252def pad_none(iterable):
253 """Returns the sequence of elements and then returns ``None`` indefinitely.
254
255 >>> take(5, pad_none(range(3)))
256 [0, 1, 2, None, None]
257
258 Useful for emulating the behavior of the built-in :func:`map` function.
259
260 See also :func:`padded`.
261
262 """
263 return chain(iterable, repeat(None))
264
265
266padnone = pad_none
267
268
269def ncycles(iterable, n):
270 """Returns the sequence elements *n* times
271
272 >>> list(ncycles(["a", "b"], 3))
273 ['a', 'b', 'a', 'b', 'a', 'b']
274
275 """
276 return chain.from_iterable(repeat(tuple(iterable), n))
277
278
279def dotproduct(vec1, vec2):
280 """Returns the dot product of the two iterables.
281
282 >>> dotproduct([10, 15, 12], [0.65, 0.80, 1.25])
283 33.5
284 >>> 10 * 0.65 + 15 * 0.80 + 12 * 1.25
285 33.5
286
287 In Python 3.12 and later, use ``math.sumprod()`` instead.
288 """
289 return sum(map(mul, vec1, vec2))
290
291
292# math.sumprod is available for Python 3.12+
293try:
294 from math import sumprod as _sumprod
295except ImportError: # pragma: no cover
296 _sumprod = dotproduct
297
298
299def flatten(list_of_lists):
300 """Return an iterator flattening one level of nesting in a list of lists.
301
302 >>> list(flatten([[0, 1], [2, 3]]))
303 [0, 1, 2, 3]
304
305 See also :func:`collapse`, which can flatten multiple levels of nesting.
306
307 """
308 return chain.from_iterable(list_of_lists)
309
310
311def repeatfunc(function, times=None, *args):
312 """Call *function* with *args* repeatedly, returning an iterable over the
313 results.
314
315 If *times* is specified, the iterable will terminate after that many
316 repetitions:
317
318 >>> from operator import add
319 >>> times = 4
320 >>> args = 3, 5
321 >>> list(repeatfunc(add, times, *args))
322 [8, 8, 8, 8]
323
324 If *times* is ``None`` the iterable will not terminate:
325
326 >>> from random import randrange
327 >>> times = None
328 >>> args = 1, 11
329 >>> take(6, repeatfunc(randrange, times, *args)) # doctest:+SKIP
330 [2, 4, 8, 1, 8, 4]
331
332 """
333 if times is None:
334 return starmap(function, repeat(args))
335 return starmap(function, repeat(args, times))
336
337
338def pairwise(iterable):
339 """
340 Wrapper for :func:`itertools.pairwise`.
341
342 .. warning::
343
344 This function is deprecated as of version 11.0.0. It will be removed in a future
345 major release.
346 """
347 return itertools_pairwise(iterable)
348
349
350def grouper(iterable, n, incomplete='fill', fillvalue=None):
351 """Group elements from *iterable* into fixed-length groups of length *n*.
352
353 >>> list(grouper('ABCDEF', 3))
354 [('A', 'B', 'C'), ('D', 'E', 'F')]
355
356 The keyword arguments *incomplete* and *fillvalue* control what happens for
357 iterables whose length is not a multiple of *n*.
358
359 When *incomplete* is `'fill'`, the last group will contain instances of
360 *fillvalue*.
361
362 >>> list(grouper('ABCDEFG', 3, incomplete='fill', fillvalue='x'))
363 [('A', 'B', 'C'), ('D', 'E', 'F'), ('G', 'x', 'x')]
364
365 When *incomplete* is `'ignore'`, the last group will not be emitted.
366
367 >>> list(grouper('ABCDEFG', 3, incomplete='ignore', fillvalue='x'))
368 [('A', 'B', 'C'), ('D', 'E', 'F')]
369
370 When *incomplete* is `'strict'`, a `ValueError` will be raised.
371
372 >>> iterator = grouper('ABCDEFG', 3, incomplete='strict')
373 >>> list(iterator) # doctest: +IGNORE_EXCEPTION_DETAIL
374 Traceback (most recent call last):
375 ...
376 ValueError
377
378 """
379 iterators = [iter(iterable)] * n
380 match incomplete:
381 case 'fill':
382 return zip_longest(*iterators, fillvalue=fillvalue)
383 case 'strict':
384 return zip(*iterators, strict=True)
385 case 'ignore':
386 return zip(*iterators)
387 case _:
388 raise ValueError('Expected fill, strict, or ignore')
389
390
391def roundrobin(*iterables):
392 """Visit input iterables in a cycle until each is exhausted.
393
394 >>> list(roundrobin('ABC', 'D', 'EF'))
395 ['A', 'D', 'E', 'B', 'F', 'C']
396
397 This function produces the same output as :func:`interleave_longest`, but
398 may perform better for some inputs (in particular when the number of
399 iterables is small).
400
401 """
402 # Algorithm credited to George Sakkis
403 iterators = map(iter, iterables)
404 for num_active in range(len(iterables), 0, -1):
405 iterators = cycle(islice(iterators, num_active))
406 yield from map(next, iterators)
407
408
409def partition(pred, iterable):
410 """
411 Returns a 2-tuple of iterables derived from the input iterable.
412 The first yields the items that have ``pred(item) == False``.
413 The second yields the items that have ``pred(item) == True``.
414
415 >>> is_odd = lambda x: x % 2 != 0
416 >>> iterable = range(10)
417 >>> even_items, odd_items = partition(is_odd, iterable)
418 >>> list(even_items), list(odd_items)
419 ([0, 2, 4, 6, 8], [1, 3, 5, 7, 9])
420
421 If *pred* is None, :func:`bool` is used.
422
423 >>> iterable = [0, 1, False, True, '', ' ']
424 >>> false_items, true_items = partition(None, iterable)
425 >>> list(false_items), list(true_items)
426 ([0, False, ''], [1, True, ' '])
427
428 """
429 if pred is None:
430 pred = bool
431 iterator = iter(iterable)
432
433 false_queue = deque()
434 true_queue = deque()
435
436 def gen(queue):
437 while True:
438 while queue:
439 yield queue.popleft()
440 for value in iterator:
441 (true_queue if pred(value) else false_queue).append(value)
442 break
443 else:
444 return
445
446 return gen(false_queue), gen(true_queue)
447
448
449def powerset(iterable):
450 """Yields all possible subsets of the iterable.
451
452 >>> list(powerset([1, 2, 3]))
453 [(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]
454
455 :func:`powerset` will operate on iterables that aren't :class:`set`
456 instances, so repeated elements in the input will produce repeated elements
457 in the output.
458
459 >>> seq = [1, 1, 0]
460 >>> list(powerset(seq))
461 [(), (1,), (1,), (0,), (1, 1), (1, 0), (1, 0), (1, 1, 0)]
462
463 For a variant that efficiently yields actual :class:`set` instances, see
464 :func:`powerset_of_sets`.
465 """
466 s = list(iterable)
467 return chain.from_iterable(combinations(s, r) for r in range(len(s) + 1))
468
469
470def unique_everseen(iterable, key=None):
471 """Yield unique elements, preserving order. Remember all elements ever seen.
472
473 >>> list(unique_everseen('AAAABBBCCDAABBB'))
474 ['A', 'B', 'C', 'D']
475 >>> list(unique_everseen('ABBCcAD', str.casefold))
476 ['A', 'B', 'C', 'D']
477
478 Raises ``TypeError`` for unhashable items.
479
480 Some unhashable objects can be converted to hashable objects
481 using the *key* parameter:
482
483 * For ``list`` objects, try ``key=tuple``.
484 * For ``set`` objects, try ``key=frozenset``.
485 * For ``dict`` objects, try ``key=lambda x: frozenset(x.items())``
486 or in Python 3.15 and later, set ``key=frozendict``.
487
488 Alternatively, consider the ``unique()`` itertool recipe. It sorts
489 the data and then uses equality to eliminate duplicates. Hashability
490 is not required.
491
492 """
493 seen = set()
494 if key is None:
495 for element in filterfalse(seen.__contains__, iterable):
496 seen.add(element)
497 yield element
498 else:
499 for element in iterable:
500 k = key(element)
501 if k not in seen:
502 seen.add(k)
503 yield element
504
505
506def unique_justseen(iterable, key=None):
507 """Yields elements in order, ignoring serial duplicates
508
509 >>> list(unique_justseen('AAAABBBCCDAABBB'))
510 ['A', 'B', 'C', 'D', 'A', 'B']
511 >>> list(unique_justseen('ABBCcAD', str.lower))
512 ['A', 'B', 'C', 'A', 'D']
513
514 """
515 if key is None:
516 return map(itemgetter(0), groupby(iterable))
517
518 return map(next, map(itemgetter(1), groupby(iterable, key)))
519
520
521def unique(iterable, key=None, reverse=False):
522 """Yields unique elements in sorted order.
523
524 >>> list(unique([[1, 2], [3, 4], [1, 2]]))
525 [[1, 2], [3, 4]]
526
527 *key* and *reverse* are passed to :func:`sorted`.
528
529 >>> list(unique('ABBcCAD', str.casefold))
530 ['A', 'B', 'c', 'D']
531 >>> list(unique('ABBcCAD', str.casefold, reverse=True))
532 ['D', 'c', 'B', 'A']
533
534 The elements in *iterable* need not be hashable, but they must be
535 comparable for sorting to work.
536 """
537 sequenced = sorted(iterable, key=key, reverse=reverse)
538 return unique_justseen(sequenced, key=key)
539
540
541def iter_except(function, exception, first=None):
542 """Yields results from a function repeatedly until an exception is raised.
543
544 Converts a call-until-exception interface to an iterator interface.
545 Like ``iter(function, sentinel)``, but uses an exception instead of a sentinel
546 to end the loop.
547
548 >>> l = [0, 1, 2]
549 >>> list(iter_except(l.pop, IndexError))
550 [2, 1, 0]
551
552 Multiple exceptions can be specified as a stopping condition:
553
554 >>> l = [1, 2, 3, '...', 4, 5, 6]
555 >>> list(iter_except(lambda: 1 + l.pop(), (IndexError, TypeError)))
556 [7, 6, 5]
557 >>> list(iter_except(lambda: 1 + l.pop(), (IndexError, TypeError)))
558 [4, 3, 2]
559 >>> list(iter_except(lambda: 1 + l.pop(), (IndexError, TypeError)))
560 []
561
562 """
563 with suppress(exception):
564 if first is not None:
565 yield first()
566 while True:
567 yield function()
568
569
570def first_true(iterable, default=None, pred=None):
571 """
572 Returns the first true value in the iterable.
573
574 If no true value is found, returns *default*
575
576 If *pred* is not None, returns the first item for which
577 ``pred(item) == True`` .
578
579 >>> first_true(range(10))
580 1
581 >>> first_true(range(10), pred=lambda x: x > 5)
582 6
583 >>> first_true(range(10), default='missing', pred=lambda x: x > 9)
584 'missing'
585
586 """
587 return next(filter(pred, iterable), default)
588
589
590def random_product(*iterables, repeat=1):
591 """Draw an item at random from each of the input iterables.
592
593 >>> random_product('abc', range(4), 'XYZ') # doctest:+SKIP
594 ('c', 3, 'Z')
595
596 If *repeat* is provided as a keyword argument, that many items will be
597 drawn from each iterable.
598
599 >>> random_product('abcd', range(4), repeat=2) # doctest:+SKIP
600 ('a', 2, 'd', 3)
601
602 This equivalent to taking a random selection from
603 ``itertools.product(*args, repeat=repeat)``.
604
605 """
606 pools = tuple(map(tuple, iterables)) * repeat
607 return tuple(map(choice, pools))
608
609
610def random_permutation(iterable, r=None):
611 """Return a random *r* length permutation of the elements in *iterable*.
612
613 If *r* is not specified or is ``None``, then *r* defaults to the length of
614 *iterable*.
615
616 >>> random_permutation(range(5)) # doctest:+SKIP
617 (3, 4, 0, 1, 2)
618
619 This equivalent to taking a random selection from
620 ``itertools.permutations(iterable, r)``.
621
622 """
623 pool = tuple(iterable)
624 r = len(pool) if r is None else r
625 return tuple(sample(pool, r))
626
627
628def random_combination(iterable, r):
629 """Return a random *r* length subsequence of the elements in *iterable*.
630
631 >>> random_combination(range(5), 3) # doctest:+SKIP
632 (2, 3, 4)
633
634 This equivalent to taking a random selection from
635 ``itertools.combinations(iterable, r)``.
636
637 """
638 pool = tuple(iterable)
639 n = len(pool)
640 indices = sorted(sample(range(n), r))
641 return tuple([pool[i] for i in indices])
642
643
644def random_combination_with_replacement(iterable, r):
645 """Return a random *r* length subsequence of elements in *iterable*,
646 allowing individual elements to be repeated.
647
648 >>> random_combination_with_replacement(range(3), 5) # doctest:+SKIP
649 (0, 0, 1, 2, 2)
650
651 This equivalent to taking a random selection from
652 ``itertools.combinations_with_replacement(iterable, r)``.
653
654 """
655 pool = tuple(iterable)
656 n = len(pool)
657 indices = sorted(randrange(n) for i in range(r))
658 return tuple([pool[i] for i in indices])
659
660
661def nth_combination(iterable, r, index):
662 """Equivalent to ``list(combinations(iterable, r))[index]``.
663
664 The subsequences of *iterable* that are of length *r* can be ordered
665 lexicographically. :func:`nth_combination` computes the subsequence at
666 sort position *index* directly, without computing the previous
667 subsequences.
668
669 >>> nth_combination(range(5), 3, 5)
670 (0, 3, 4)
671
672 ``ValueError`` will be raised If *r* is negative.
673 ``IndexError`` will be raised if the given *index* is invalid.
674 """
675 pool = tuple(iterable)
676 n = len(pool)
677 c = comb(n, r)
678
679 if index < 0:
680 index += c
681 if not 0 <= index < c:
682 raise IndexError
683
684 result = []
685 while r:
686 c, n, r = c * r // n, n - 1, r - 1
687 while index >= c:
688 index -= c
689 c, n = c * (n - r) // n, n - 1
690 result.append(pool[-1 - n])
691
692 return tuple(result)
693
694
695def prepend(value, iterable):
696 """Yield *value*, followed by the elements in *iterable*.
697
698 >>> value = '0'
699 >>> iterable = ['1', '2', '3']
700 >>> list(prepend(value, iterable))
701 ['0', '1', '2', '3']
702
703 To prepend multiple values, see :func:`itertools.chain`
704 or :func:`value_chain`.
705
706 """
707 return chain([value], iterable)
708
709
710def convolve(signal, kernel):
711 """Discrete linear convolution of two iterables.
712 Equivalent to polynomial multiplication.
713
714 For example, multiplying ``(x² -x - 20)`` by ``(x - 3)``
715 gives ``(x³ -4x² -17x + 60)``.
716
717 >>> list(convolve([1, -1, -20], [1, -3]))
718 [1, -4, -17, 60]
719
720 Examples of popular kinds of kernels:
721
722 * The kernel ``[0.25, 0.25, 0.25, 0.25]`` computes a moving average.
723 For image data, this blurs the image and reduces noise.
724 * The kernel ``[1/2, 0, -1/2]`` estimates the first derivative of
725 a function evaluated at evenly spaced inputs.
726 * The kernel ``[1, -2, 1]`` estimates the second derivative of a
727 function evaluated at evenly spaced inputs.
728
729 Convolutions are mathematically commutative; however, the inputs are
730 evaluated differently. The signal is consumed lazily and can be
731 infinite. The kernel is fully consumed before the calculations begin.
732
733 Supports all numeric types: int, float, complex, Decimal, Fraction.
734
735 References:
736
737 * Article: https://betterexplained.com/articles/intuitive-convolution/
738 * Video by 3Blue1Brown: https://www.youtube.com/watch?v=KuXjwB4LzSA
739
740 """
741 # This implementation comes from an older version of the itertools
742 # documentation. While the newer implementation is a bit clearer,
743 # this one was kept because the inlined window logic is faster
744 # and it avoids an unnecessary deque-to-tuple conversion.
745 kernel = tuple(kernel)[::-1]
746 n = len(kernel)
747 window = deque([0], maxlen=n) * n
748 for x in chain(signal, repeat(0, n - 1)):
749 window.append(x)
750 yield _sumprod(kernel, window)
751
752
753def before_and_after(predicate, it):
754 """A variant of :func:`takewhile` that allows complete access to the
755 remainder of the iterator.
756
757 >>> it = iter('ABCdEfGhI')
758 >>> all_upper, remainder = before_and_after(str.isupper, it)
759 >>> ''.join(all_upper)
760 'ABC'
761 >>> ''.join(remainder) # takewhile() would lose the 'd'
762 'dEfGhI'
763
764 Note that the first iterator must be fully consumed before the second
765 iterator can generate valid results.
766 """
767 trues, after = tee(it)
768 trues = compress(takewhile(predicate, trues), zip(after))
769 return trues, after
770
771
772def triplewise(iterable):
773 """Return overlapping triplets from *iterable*.
774
775 >>> list(triplewise('ABCDE'))
776 [('A', 'B', 'C'), ('B', 'C', 'D'), ('C', 'D', 'E')]
777
778 """
779 # This deviates from the itertools documentation recipe - see
780 # https://github.com/more-itertools/more-itertools/issues/889
781 t1, t2, t3 = tee(iterable, 3)
782 next(t3, None)
783 next(t3, None)
784 next(t2, None)
785 return zip(t1, t2, t3)
786
787
788def _sliding_window_islice(iterable, n):
789 # Fast path for small, non-zero values of n.
790 iterators = tee(iterable, n)
791 for i, iterator in enumerate(iterators):
792 next(islice(iterator, i, i), None)
793 return zip(*iterators)
794
795
796def _sliding_window_deque(iterable, n):
797 # Normal path for other values of n.
798 iterator = iter(iterable)
799 window = deque(islice(iterator, n - 1), maxlen=n)
800 for x in iterator:
801 window.append(x)
802 yield tuple(window)
803
804
805def sliding_window(iterable, n):
806 """Return a sliding window of width *n* over *iterable*.
807
808 >>> list(sliding_window(range(6), 4))
809 [(0, 1, 2, 3), (1, 2, 3, 4), (2, 3, 4, 5)]
810
811 If *iterable* has fewer than *n* items, then nothing is yielded:
812
813 >>> list(sliding_window(range(3), 4))
814 []
815
816 For a variant with more features, see :func:`windowed`.
817 """
818 if n > 20:
819 return _sliding_window_deque(iterable, n)
820 elif n > 2:
821 return _sliding_window_islice(iterable, n)
822 elif n == 2:
823 return pairwise(iterable)
824 elif n == 1:
825 return zip(iterable)
826 else:
827 raise ValueError(f'n should be at least one, not {n}')
828
829
830def subslices(iterable):
831 """Return all contiguous non-empty subslices of *iterable*.
832
833 >>> list(subslices('ABC'))
834 [['A'], ['A', 'B'], ['A', 'B', 'C'], ['B'], ['B', 'C'], ['C']]
835
836 This is similar to :func:`substrings`, but emits items in a different
837 order.
838 """
839 seq = list(iterable)
840 slices = starmap(slice, combinations(range(len(seq) + 1), 2))
841 return map(getitem, repeat(seq), slices)
842
843
844def polynomial_from_roots(roots):
845 """Compute a polynomial's coefficients from its roots.
846
847 >>> roots = [5, -4, 3] # (x - 5) * (x + 4) * (x - 3)
848 >>> polynomial_from_roots(roots) # x³ - 4 x² - 17 x + 60
849 [1, -4, -17, 60]
850
851 Note that polynomial coefficients are specified in descending power order.
852
853 Supports all numeric types: int, float, complex, Decimal, Fraction.
854 """
855
856 # This recipe differs from the one in itertools docs in that it
857 # applies list() after each call to convolve(). This avoids
858 # hitting stack limits with nested generators.
859
860 poly = [1]
861 for root in roots:
862 poly = list(convolve(poly, (1, -root)))
863 return poly
864
865
866def iter_index(iterable, value, start=0, stop=None):
867 """Yield the index of each place in *iterable* that *value* occurs,
868 beginning with index *start* and ending before index *stop*.
869
870
871 >>> list(iter_index('AABCADEAF', 'A'))
872 [0, 1, 4, 7]
873 >>> list(iter_index('AABCADEAF', 'A', 1)) # start index is inclusive
874 [1, 4, 7]
875 >>> list(iter_index('AABCADEAF', 'A', 1, 7)) # stop index is not inclusive
876 [1, 4]
877
878 The behavior for non-scalar *values* matches the built-in Python types.
879
880 >>> list(iter_index('ABCDABCD', 'AB'))
881 [0, 4]
882 >>> list(iter_index([0, 1, 2, 3, 0, 1, 2, 3], [0, 1]))
883 []
884 >>> list(iter_index([[0, 1], [2, 3], [0, 1], [2, 3]], [0, 1]))
885 [0, 2]
886
887 See :func:`locate` for a more general means of finding the indexes
888 associated with particular values.
889
890 """
891 seq_index = getattr(iterable, 'index', None)
892 if seq_index is None:
893 # Slow path for general iterables
894 iterator = islice(iterable, start, stop)
895 for i, element in enumerate(iterator, start):
896 if element is value or element == value:
897 yield i
898 else:
899 # Fast path for sequences
900 stop = len(iterable) if stop is None else stop
901 i = start - 1
902 with suppress(ValueError):
903 while True:
904 yield (i := seq_index(value, i + 1, stop))
905
906
907def sieve(n):
908 """Yield the primes less than n.
909
910 >>> list(sieve(30))
911 [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
912
913 """
914 # This implementation comes from an older version of the itertools
915 # documentation. The newer implementation is easier to read but is
916 # less lazy.
917 if n > 2:
918 yield 2
919 start = 3
920 data = bytearray((0, 1)) * (n // 2)
921 for p in iter_index(data, 1, start, stop=isqrt(n) + 1):
922 yield from iter_index(data, 1, start, p * p)
923 data[p * p : n : p + p] = bytes(len(range(p * p, n, p + p)))
924 start = p * p
925 yield from iter_index(data, 1, start)
926
927
928def _batched(iterable, n, *, strict=False): # pragma: no cover
929 """Batch data into tuples of length *n*. If the number of items in
930 *iterable* is not divisible by *n*:
931 * The last batch will be shorter if *strict* is ``False``.
932 * :exc:`ValueError` will be raised if *strict* is ``True``.
933
934 >>> list(batched('ABCDEFG', 3))
935 [('A', 'B', 'C'), ('D', 'E', 'F'), ('G',)]
936
937 On Python 3.13 and above, this is an alias for :func:`itertools.batched`.
938 """
939 if n < 1:
940 raise ValueError('n must be at least one')
941 iterator = iter(iterable)
942 while batch := tuple(islice(iterator, n)):
943 if strict and len(batch) != n:
944 raise ValueError('batched(): incomplete batch')
945 yield batch
946
947
948if hexversion >= 0x30D00A2: # pragma: no cover
949 from itertools import batched as itertools_batched
950
951 def batched(iterable, n, *, strict=False):
952 return itertools_batched(iterable, n, strict=strict)
953
954 batched.__doc__ = _batched.__doc__
955else: # pragma: no cover
956 batched = _batched
957
958
959def transpose(matrix):
960 """Swap the rows and columns of the input matrix.
961
962 >>> list(transpose([(1, 2, 3), (11, 22, 33)]))
963 [(1, 11), (2, 22), (3, 33)]
964
965 The caller should ensure that the dimensions of the input are compatible.
966 If the input is empty, no output will be produced.
967 """
968 return zip(*matrix, strict=True)
969
970
971def _is_scalar(value, stringlike=(str, bytes)):
972 "Scalars are bytes, strings, and non-iterables."
973 try:
974 iter(value)
975 except TypeError:
976 return True
977 return isinstance(value, stringlike)
978
979
980def _flatten_tensor(tensor):
981 "Depth-first iterator over scalars in a tensor."
982 iterator = iter(tensor)
983 while True:
984 try:
985 value = next(iterator)
986 except StopIteration:
987 return iterator
988 iterator = chain((value,), iterator)
989 if _is_scalar(value):
990 return iterator
991 iterator = chain.from_iterable(iterator)
992
993
994def reshape(matrix, shape):
995 """Change the shape of a *matrix*.
996
997 If *shape* is an integer, the matrix must be two dimensional
998 and the shape is interpreted as the desired number of columns:
999
1000 >>> matrix = [(0, 1), (2, 3), (4, 5)]
1001 >>> cols = 3
1002 >>> list(reshape(matrix, cols))
1003 [(0, 1, 2), (3, 4, 5)]
1004
1005 If *shape* is a tuple (or other iterable), the input matrix can have
1006 any number of dimensions. It will first be flattened and then rebuilt
1007 to the desired shape which can also be multidimensional:
1008
1009 >>> matrix = [(0, 1), (2, 3), (4, 5)] # Start with a 3 x 2 matrix
1010
1011 >>> list(reshape(matrix, (2, 3))) # Make a 2 x 3 matrix
1012 [(0, 1, 2), (3, 4, 5)]
1013
1014 >>> list(reshape(matrix, (6,))) # Make a vector of length six
1015 [0, 1, 2, 3, 4, 5]
1016
1017 >>> list(reshape(matrix, (2, 1, 3, 1))) # Make 2 x 1 x 3 x 1 tensor
1018 [(((0,), (1,), (2,)),), (((3,), (4,), (5,)),)]
1019
1020 Each dimension is assumed to be uniform, either all arrays or all scalars.
1021 Flattening stops when the first value in a dimension is a scalar.
1022 Scalars are bytes, strings, and non-iterables.
1023 The reshape iterator stops when the requested shape is complete
1024 or when the input is exhausted, whichever comes first.
1025
1026 """
1027 if isinstance(shape, int):
1028 return batched(chain.from_iterable(matrix), shape)
1029 first_dim, *dims = shape
1030 scalar_stream = _flatten_tensor(matrix)
1031 reshaped = reduce(batched, reversed(dims), scalar_stream)
1032 return islice(reshaped, first_dim)
1033
1034
1035def matmul(m1, m2):
1036 """Multiply two matrices.
1037
1038 >>> list(matmul([(7, 5), (3, 5)], [(2, 5), (7, 9)]))
1039 [(49, 80), (41, 60)]
1040
1041 The caller should ensure that the dimensions of the input matrices are
1042 compatible with each other.
1043
1044 Supports all numeric types: int, float, complex, Decimal, Fraction.
1045 """
1046 n = len(m2[0])
1047 return batched(starmap(_sumprod, product(m1, transpose(m2))), n)
1048
1049
1050def _factor_pollard(n):
1051 # Return a factor of n using Pollard's rho algorithm.
1052 # Efficient when n is odd and composite.
1053 for b in range(1, n):
1054 x = y = 2
1055 d = 1
1056 while d == 1:
1057 x = (x * x + b) % n
1058 y = (y * y + b) % n
1059 y = (y * y + b) % n
1060 d = gcd(x - y, n)
1061 if d != n:
1062 return d
1063 raise ValueError('prime or under 5') # pragma: no cover
1064
1065
1066_primes_below_211 = tuple(sieve(211))
1067
1068
1069def factor(n):
1070 """Yield the prime factors of n.
1071
1072 >>> list(factor(360))
1073 [2, 2, 2, 3, 3, 5]
1074
1075 Finds small factors with trial division. Larger factors are
1076 either verified as prime with ``is_prime`` or split into
1077 smaller factors with Pollard's rho algorithm.
1078 """
1079
1080 # Corner case reduction
1081 if n < 2:
1082 return
1083
1084 # Trial division reduction
1085 for prime in _primes_below_211:
1086 while not n % prime:
1087 yield prime
1088 n //= prime
1089
1090 # Pollard's rho reduction
1091 primes = []
1092 todo = [n] if n > 1 else []
1093 for n in todo:
1094 if n < 211**2 or is_prime(n):
1095 primes.append(n)
1096 else:
1097 fact = _factor_pollard(n)
1098 todo += (fact, n // fact)
1099 yield from sorted(primes)
1100
1101
1102def polynomial_eval(coefficients, x):
1103 """Evaluate a polynomial at a specific value.
1104
1105 Computes with better numeric stability than Horner's method.
1106
1107 Evaluate ``x^3 - 4 * x^2 - 17 * x + 60`` at ``x = 2.5``:
1108
1109 >>> coefficients = [1, -4, -17, 60]
1110 >>> x = 2.5
1111 >>> polynomial_eval(coefficients, x)
1112 8.125
1113
1114 Note that polynomial coefficients are specified in descending power order.
1115
1116 Supports all numeric types: int, float, complex, Decimal, Fraction.
1117 """
1118 n = len(coefficients)
1119 if n == 0:
1120 return type(x)(0)
1121 powers = map(pow, repeat(x), reversed(range(n)))
1122 return _sumprod(coefficients, powers)
1123
1124
1125def sum_of_squares(iterable):
1126 """Return the sum of the squares of the input values.
1127
1128 >>> sum_of_squares([10, 20, 30])
1129 1400
1130
1131 Supports all numeric types: int, float, complex, Decimal, Fraction.
1132 """
1133 return _sumprod(*tee(iterable))
1134
1135
1136def polynomial_derivative(coefficients):
1137 """Compute the first derivative of a polynomial.
1138
1139 Evaluate the derivative of ``x³ - 4 x² - 17 x + 60``:
1140
1141 >>> coefficients = [1, -4, -17, 60]
1142 >>> derivative_coefficients = polynomial_derivative(coefficients)
1143 >>> derivative_coefficients
1144 [3, -8, -17]
1145
1146 Note that polynomial coefficients are specified in descending power order.
1147
1148 Supports all numeric types: int, float, complex, Decimal, Fraction.
1149 """
1150 n = len(coefficients)
1151 powers = reversed(range(1, n))
1152 return list(map(mul, coefficients, powers))
1153
1154
1155def totient(n):
1156 """Return the count of natural numbers up to *n* that are coprime with *n*.
1157
1158 Euler's totient function φ(n) gives the number of totatives.
1159 Totative are integers k in the range 1 ≤ k ≤ n such that gcd(n, k) = 1.
1160
1161 >>> n = 9
1162 >>> totient(n)
1163 6
1164
1165 >>> totatives = [x for x in range(1, n) if gcd(n, x) == 1]
1166 >>> totatives
1167 [1, 2, 4, 5, 7, 8]
1168 >>> len(totatives)
1169 6
1170
1171 Reference: https://en.wikipedia.org/wiki/Euler%27s_totient_function
1172
1173 """
1174 for prime in set(factor(n)):
1175 n -= n // prime
1176 return n
1177
1178
1179# Miller–Rabin primality test: https://oeis.org/A014233
1180_perfect_tests = [
1181 (2047, (2,)),
1182 (9080191, (31, 73)),
1183 (4759123141, (2, 7, 61)),
1184 (1122004669633, (2, 13, 23, 1662803)),
1185 (2152302898747, (2, 3, 5, 7, 11)),
1186 (3474749660383, (2, 3, 5, 7, 11, 13)),
1187 (18446744073709551616, (2, 325, 9375, 28178, 450775, 9780504, 1795265022)),
1188 (
1189 3317044064679887385961981,
1190 (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41),
1191 ),
1192]
1193
1194
1195@lru_cache
1196def _shift_to_odd(n):
1197 'Return s, d such that 2**s * d == n'
1198 s = ((n - 1) ^ n).bit_length() - 1
1199 d = n >> s
1200 assert (1 << s) * d == n and d & 1 and s >= 0
1201 return s, d
1202
1203
1204def _strong_probable_prime(n, base):
1205 assert (n > 2) and (n & 1) and (2 <= base < n)
1206
1207 s, d = _shift_to_odd(n - 1)
1208
1209 x = pow(base, d, n)
1210 if x == 1 or x == n - 1:
1211 return True
1212
1213 for _ in range(s - 1):
1214 x = x * x % n
1215 if x == n - 1:
1216 return True
1217
1218 return False
1219
1220
1221# Separate instance of Random() that doesn't share state
1222# with the default user instance of Random().
1223_private_randrange = random.Random().randrange
1224
1225
1226def is_prime(n):
1227 """Return ``True`` if *n* is prime and ``False`` otherwise.
1228
1229 Basic examples:
1230
1231 >>> is_prime(37)
1232 True
1233 >>> is_prime(3 * 13)
1234 False
1235 >>> is_prime(18_446_744_073_709_551_557)
1236 True
1237
1238 Find the next prime over one billion:
1239
1240 >>> next(filter(is_prime, count(10**9)))
1241 1000000007
1242
1243 Generate random primes up to 200 bits and up to 60 decimal digits:
1244
1245 >>> from random import seed, randrange, getrandbits
1246 >>> seed(18675309)
1247
1248 >>> next(filter(is_prime, map(getrandbits, repeat(200))))
1249 893303929355758292373272075469392561129886005037663238028407
1250
1251 >>> next(filter(is_prime, map(randrange, repeat(10**60))))
1252 269638077304026462407872868003560484232362454342414618963649
1253
1254 This function is exact for values of *n* below 10**24. For larger inputs,
1255 the probabilistic Miller-Rabin primality test has a less than 1 in 2**128
1256 chance of a false positive.
1257 """
1258
1259 if n < 17:
1260 return n in {2, 3, 5, 7, 11, 13}
1261
1262 if not (n & 1 and n % 3 and n % 5 and n % 7 and n % 11 and n % 13):
1263 return False
1264
1265 for limit, bases in _perfect_tests:
1266 if n < limit:
1267 break
1268 else:
1269 bases = (_private_randrange(2, n - 1) for i in range(64))
1270
1271 return all(_strong_probable_prime(n, base) for base in bases)
1272
1273
1274def loops(n):
1275 """Returns an iterable with *n* elements for efficient looping.
1276 Like ``range(n)`` but doesn't create integers.
1277
1278 >>> i = 0
1279 >>> for _ in loops(5):
1280 ... i += 1
1281 >>> i
1282 5
1283
1284 """
1285 return repeat(None, n)
1286
1287
1288def multinomial(*counts):
1289 """Number of distinct arrangements of a multiset.
1290
1291 The expression ``multinomial(3, 4, 2)`` has several equivalent
1292 interpretations:
1293
1294 * In the expansion of ``(a + b + c)⁹``, the coefficient of the
1295 ``a³b⁴c²`` term is 1260.
1296
1297 * There are 1260 distinct ways to arrange 9 balls consisting of 3 reds, 4
1298 greens, and 2 blues.
1299
1300 * There are 1260 unique ways to place 9 distinct objects into three bins
1301 with sizes 3, 4, and 2.
1302
1303 The :func:`multinomial` function computes the length of
1304 :func:`distinct_permutations`. For example, there are 83,160 distinct
1305 anagrams of the word "abracadabra":
1306
1307 >>> from more_itertools import distinct_permutations, ilen
1308 >>> ilen(distinct_permutations('abracadabra'))
1309 83160
1310
1311 This can be computed directly from the letter counts, 5a 2b 2r 1c 1d:
1312
1313 >>> from collections import Counter
1314 >>> list(Counter('abracadabra').values())
1315 [5, 2, 2, 1, 1]
1316 >>> multinomial(5, 2, 2, 1, 1)
1317 83160
1318
1319 A binomial coefficient is a special case of multinomial where there are
1320 only two categories. For example, the number of ways to arrange 12 balls
1321 with 5 reds and 7 blues is ``multinomial(5, 7)`` or ``math.comb(12, 5)``.
1322
1323 Likewise, factorial is a special case of multinomial where
1324 the multiplicities are all just 1 so that
1325 ``multinomial(1, 1, 1, 1, 1, 1, 1) == math.factorial(7)``.
1326
1327 Reference: https://en.wikipedia.org/wiki/Multinomial_theorem
1328
1329 """
1330 return prod(map(comb, accumulate(counts), counts))
1331
1332
1333def _running_median_minheap_and_maxheap(iterator): # pragma: no cover
1334 "Non-windowed running_median() for Python 3.14+"
1335
1336 read = iterator.__next__
1337 lo = [] # max-heap
1338 hi = [] # min-heap (same size as or one smaller than lo)
1339
1340 with suppress(StopIteration):
1341 while True:
1342 heappush_max(lo, heappushpop(hi, read()))
1343 yield lo[0]
1344
1345 heappush(hi, heappushpop_max(lo, read()))
1346 yield (lo[0] + hi[0]) / 2
1347
1348
1349def _running_median_minheap_only(iterator): # pragma: no cover
1350 "Backport of non-windowed running_median() for Python 3.13 and prior."
1351
1352 read = iterator.__next__
1353 lo = [] # max-heap (actually a minheap with negated values)
1354 hi = [] # min-heap (same size as or one smaller than lo)
1355
1356 with suppress(StopIteration):
1357 while True:
1358 heappush(lo, -heappushpop(hi, read()))
1359 yield -lo[0]
1360
1361 heappush(hi, -heappushpop(lo, -read()))
1362 yield (hi[0] - lo[0]) / 2
1363
1364
1365def _running_median_windowed(iterator, maxlen):
1366 "Yield median of values in a sliding window."
1367
1368 window = deque()
1369 ordered = []
1370
1371 for x in iterator:
1372 window.append(x)
1373 insort(ordered, x)
1374
1375 if len(ordered) > maxlen:
1376 i = bisect_left(ordered, window.popleft())
1377 del ordered[i]
1378
1379 n = len(ordered)
1380 m = n // 2
1381 yield ordered[m] if n & 1 else (ordered[m - 1] + ordered[m]) / 2
1382
1383
1384def running_median(iterable, *, maxlen=None):
1385 """Cumulative median of values seen so far or values in a sliding window.
1386
1387 Set *maxlen* to a positive integer to specify the maximum size
1388 of the sliding window. The default of *None* is equivalent to
1389 an unbounded window.
1390
1391 For example:
1392
1393 >>> list(running_median([5.0, 9.0, 4.0, 12.0, 8.0, 9.0]))
1394 [5.0, 7.0, 5.0, 7.0, 8.0, 8.5]
1395 >>> list(running_median([5.0, 9.0, 4.0, 12.0, 8.0, 9.0], maxlen=3))
1396 [5.0, 7.0, 5.0, 9.0, 8.0, 9.0]
1397
1398 Supports numeric types such as int, float, Decimal, and Fraction,
1399 but not complex numbers which are unorderable.
1400
1401 On version Python 3.13 and prior, max-heaps are simulated with
1402 negative values. The negation causes Decimal inputs to apply context
1403 rounding, making the results slightly different than that obtained
1404 by statistics.median().
1405 """
1406
1407 iterator = iter(iterable)
1408
1409 if maxlen is not None:
1410 maxlen = _index(maxlen)
1411 if maxlen <= 0:
1412 raise ValueError('Window size should be positive')
1413 return _running_median_windowed(iterator, maxlen)
1414
1415 if not _max_heap_available:
1416 return _running_median_minheap_only(iterator) # pragma: no cover
1417
1418 return _running_median_minheap_and_maxheap(iterator) # pragma: no cover
1419
1420
1421def _windowed_running_mean(iterator, n):
1422 window = deque()
1423 running_sum = 0
1424 for value in iterator:
1425 window.append(value)
1426 running_sum += value
1427 if len(window) > n:
1428 running_sum -= window.popleft()
1429 yield running_sum / len(window)
1430
1431
1432def running_mean(iterable, *, maxlen=None):
1433 """Cumulative mean of values seen so far or values in a sliding window.
1434
1435 Set *maxlen* to a positive integer to specify the maximum size
1436 of the sliding window. The default of *None* is equivalent to
1437 an unbounded window.
1438
1439 For example:
1440
1441 >>> list(running_mean([40, 30, 50, 46, 39, 44]))
1442 [40.0, 35.0, 40.0, 41.5, 41.0, 41.5]
1443
1444 >>> list(running_mean([40, 30, 50, 46, 39, 44], maxlen=3))
1445 [40.0, 35.0, 40.0, 42.0, 45.0, 43.0]
1446
1447 Supports numeric types such as int, float, complex, Decimal, and Fraction.
1448
1449 No extra effort is made to reduce round-off errors for float inputs.
1450 So the results may be slightly different from `statistics.mean`.
1451
1452 """
1453
1454 iterator = iter(iterable)
1455
1456 if maxlen is None:
1457 return map(truediv, accumulate(iterator), count(1))
1458
1459 if maxlen <= 0:
1460 raise ValueError('Window size should be positive')
1461
1462 return _windowed_running_mean(iterator, maxlen)
1463
1464
1465def _windowed_running_min(iterator, maxlen):
1466 sis = deque() # Strictly increasing subsequence
1467 for index, value in enumerate(iterator):
1468 if sis and sis[0][0] == index - maxlen:
1469 sis.popleft()
1470 while sis and not sis[-1][1] < value: # Remove non-increasing values
1471 sis.pop()
1472 sis.append((index, value)) # Most recent value at position -1
1473 yield sis[0][1] # Window minimum at position 0
1474
1475
1476def running_min(iterable, *, maxlen=None):
1477 """Smallest of values seen so far or values in a sliding window.
1478
1479 Set *maxlen* to a positive integer to specify the maximum size
1480 of the sliding window. The default of *None* is equivalent to
1481 an unbounded window.
1482
1483 For example:
1484
1485 >>> list(running_min([4, 3, 7, 0, 8, 1, 6, 2, 9, 5]))
1486 [4, 3, 3, 0, 0, 0, 0, 0, 0, 0]
1487
1488 >>> list(running_min([4, 3, 7, 0, 8, 1, 6, 2, 9, 5], maxlen=3))
1489 [4, 3, 3, 0, 0, 0, 1, 1, 2, 2]
1490
1491 Supports numeric types such as int, float, Decimal, and Fraction,
1492 but not complex numbers which are unorderable.
1493 """
1494
1495 iterator = iter(iterable)
1496
1497 if maxlen is None:
1498 return accumulate(iterator, func=min)
1499
1500 if maxlen <= 0:
1501 raise ValueError('Window size should be positive')
1502
1503 return _windowed_running_min(iterator, maxlen)
1504
1505
1506def _windowed_running_max(iterator, maxlen):
1507 sds = deque() # Strictly decreasing subsequence
1508 for index, value in enumerate(iterator):
1509 if sds and sds[0][0] == index - maxlen:
1510 sds.popleft()
1511 while sds and not sds[-1][1] > value: # Remove non-decreasing values
1512 sds.pop()
1513 sds.append((index, value)) # Most recent value at position -1
1514 yield sds[0][1] # Window maximum at position 0
1515
1516
1517def running_max(iterable, *, maxlen=None):
1518 """Largest of values seen so far or values in a sliding window.
1519
1520 Set *maxlen* to a positive integer to specify the maximum size
1521 of the sliding window. The default of *None* is equivalent to
1522 an unbounded window.
1523
1524 For example:
1525
1526 >>> list(running_max([4, 3, 7, 0, 8, 1, 6, 2, 9, 5]))
1527 [4, 4, 7, 7, 8, 8, 8, 8, 9, 9]
1528
1529 >>> list(running_max([4, 3, 7, 0, 8, 1, 6, 2, 9, 5], maxlen=3))
1530 [4, 4, 7, 7, 8, 8, 8, 6, 9, 9]
1531
1532 Supports numeric types such as int, float, Decimal, and Fraction,
1533 but not complex numbers which are unorderable.
1534 """
1535
1536 iterator = iter(iterable)
1537
1538 if maxlen is None:
1539 return accumulate(iterator, func=max)
1540
1541 if maxlen <= 0:
1542 raise ValueError('Window size should be positive')
1543
1544 return _windowed_running_max(iterator, maxlen)
1545
1546
1547@dataclass(frozen=True, slots=True)
1548class Stats:
1549 size: int
1550 minimum: float
1551 median: float
1552 maximum: float
1553 mean: float
1554
1555
1556def running_statistics(iterable, *, maxlen=None):
1557 """Statistics for values seen so far or values in a sliding window.
1558
1559 Set *maxlen* to a positive integer to specify the maximum size
1560 of the sliding window. The default of *None* is equivalent to
1561 an unbounded window.
1562
1563 Yields instances of a ``Stats`` dataclass with fields for the dataset *size*,
1564 *minimum* value, *median* value, *maximum* value, and the arithmetic *mean*.
1565
1566 Supports numeric types such as int, float, Decimal, and Fraction,
1567 but not complex numbers which are unorderable.
1568 """
1569
1570 # fmt: off
1571 t0, t1, t2, t3 = tee(iterable, 4)
1572 return map(
1573 Stats,
1574 count(1) if maxlen is None else chain(range(1, maxlen), repeat(maxlen)),
1575 running_min(t0, maxlen=maxlen),
1576 running_median(t1, maxlen=maxlen),
1577 running_max(t2, maxlen=maxlen),
1578 running_mean(t3, maxlen=maxlen),
1579 )
1580 # fmt: on
1581
1582
1583def random_derangement(iterable):
1584 """Return a random derangement of elements in the iterable.
1585
1586 Equivalent to but much faster than ``choice(list(derangements(iterable)))``.
1587
1588 """
1589 seq = tuple(iterable)
1590 if len(seq) < 2:
1591 if len(seq) == 0:
1592 return ()
1593 raise IndexError('No derangments to choose from')
1594 perm = list(range(len(seq)))
1595 start = tuple(perm)
1596 while True:
1597 shuffle(perm)
1598 if not any(map(is_, start, perm)):
1599 return itemgetter(*perm)(seq)