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