o
    g~                     @   sX  d Z ddlZddlZddlmZ ddlmZ ddlmZm	Z	 ddl
mZmZmZmZmZmZmZmZmZmZmZmZ ddlmZmZmZ ddlmZ g d	Ze Zze d
d W n e!yc   e Z"Y nw e	e d
dZ"e#eddd Z$dd Z%dddZ&dd Z'dddZ(dddZ)dddZ*e+fddZ,dd Z-e-Z.dd  Z/d!d" Z0d#d$ Z1dd%d&Z2d'd( Z3zdd)l
m4Z5 W n e6y   e3Z4Y n	w d*d+ Z4e3j e4_ G d,d- d-e7Z8d.d/ Z9d0d1 Z:dd3d4Z;d5d6 Z<d7d8 Z=d9d: Z>dd;d<Z?dd=d>Z@dd@dAZAddBdCZBddDdEZCdFdGdHdIZDddJdKZEdLdM ZFdNdO ZGdPdQ ZHdRdS ZIdTdU ZJdVdW ZKdXdY ZLdZd[ ZMd\d] ZNd^d_ ZOd`da ZPdbdc ZQddddeZRdfdg ZSd?ddhdiZTedjkrdddkl
mUZV d?ddldmZUneTZUeTj eU_ dndo ZWdpdq ZXdrds ZYdtdu ZZe[eSdvZ\dwdx Z]dydz Z^d{d| Z_d}d~ Z`dd Zag dZbedd Zcdd Zddd Zedd ZfdS )a  Imported from the recipes section of the itertools documentation.

All functions taken from the recipes section of the itertools library docs
[1]_.
Some backward-compatible usability improvements have been made.

.. [1] http://docs.python.org/library/itertools.html#recipes

    N)deque)Sized)	lru_cachepartial)chaincombinationscompresscountcyclegroupbyisliceproductrepeatstarmapteezip_longest)	randrangesamplechoice)
hexversion)0	all_equalbatchedbefore_and_afterconsumeconvolve
dotproduct
first_truefactorflattengrouperis_primeiter_except
iter_indexloopsmatmulncyclesnthnth_combinationpadnonepad_nonepairwise	partitionpolynomial_evalpolynomial_from_rootspolynomial_derivativepowersetprependquantifyreshape#random_combination_with_replacementrandom_combinationrandom_permutationrandom_product
repeatfunc
roundrobinsievesliding_window	subslicessum_of_squarestabulatetailtaketotient	transpose
triplewiseuniqueunique_everseenunique_justseenTstrictsumprodc                 C   s
   t | |S N)r   )xy rL   O/home/ubuntu/webapp/venv/lib/python3.10/site-packages/more_itertools/recipes.py<lambda>a   s   
 rN   c                 C      t t|| S )zReturn first *n* items of the iterable as a list.

        >>> take(3, range(10))
        [0, 1, 2]

    If there are fewer than *n* items in the iterable, all of them are
    returned.

        >>> take(10, range(3))
        [0, 1, 2]

    )listr   niterablerL   rL   rM   r?   d   s   r?   c                 C   s   t | t|S )a  Return an iterator over the results of ``func(start)``,
    ``func(start + 1)``, ``func(start + 2)``...

    *func* should be a function that accepts one integer argument.

    If *start* is not specified it defaults to 0. It will be incremented each
    time the iterator is advanced.

        >>> square = lambda x: x ** 2
        >>> iterator = tabulate(square, -3)
        >>> take(4, iterator)
        [9, 4, 1, 0]

    )mapr	   )functionstartrL   rL   rM   r=   t   s   r=   c                 c   sJ    t |trt|tdt||  dE dH  dS tt|| dE dH  dS )zReturn an iterator over the last *n* items of *iterable*.

    >>> t = tail(3, 'ABCDEFG')
    >>> list(t)
    ['E', 'F', 'G']

    r   Nmaxlen)
isinstancer   r   maxleniterr   rQ   rL   rL   rM   r>      s   
$r>   c                 C   s.   |du rt | dd dS tt| ||d dS )aX  Advance *iterable* by *n* steps. If *n* is ``None``, consume it
    entirely.

    Efficiently exhausts an iterator without returning values. Defaults to
    consuming the whole iterator, but an optional second argument may be
    provided to limit consumption.

        >>> i = (x for x in range(10))
        >>> next(i)
        0
        >>> consume(i, 3)
        >>> next(i)
        4
        >>> consume(i)
        >>> next(i)
        Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
        StopIteration

    If the iterator has fewer items remaining than the provided limit, the
    whole iterator will be consumed.

        >>> i = (x for x in range(3))
        >>> consume(i, 5)
        >>> next(i)
        Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
        StopIteration

    Nr   rW   )r   nextr   )iteratorrR   rL   rL   rM   r      s    r   c                 C   s   t t| |d|S )zReturns the nth item or a default value.

    >>> l = range(10)
    >>> nth(l, 3)
    3
    >>> nth(l, 20, "zebra")
    'zebra'

    N)r]   r   )rS   rR   defaultrL   rL   rM   r&      s   
r&   c                 C   s,   t | |}|D ]}|D ]}  dS  dS dS )a  
    Returns ``True`` if all the elements are equal to each other.

        >>> all_equal('aaaa')
        True
        >>> all_equal('aaab')
        False

    A function that accepts a single argument and returns a transformed version
    of each input item can be specified with *key*:

        >>> all_equal('AaaA', key=str.casefold)
        True
        >>> all_equal([1, 2, 3], key=lambda x: x < 10)
        True

    FT)r   )rS   keyr^   firstsecondrL   rL   rM   r      s   
r   c                 C   rO   )zcReturn the how many times the predicate is true.

    >>> quantify([True, False, True])
    2

    )sumrT   )rS   predrL   rL   rM   r1      s   r1   c                 C   s   t | tdS )a   Returns the sequence of elements and then returns ``None`` indefinitely.

        >>> take(5, pad_none(range(3)))
        [0, 1, 2, None, None]

    Useful for emulating the behavior of the built-in :func:`map` function.

    See also :func:`padded`.

    N)r   r   rS   rL   rL   rM   r)      s   r)   c                 C   s   t tt| |S )zvReturns the sequence elements *n* times

    >>> list(ncycles(["a", "b"], 3))
    ['a', 'b', 'a', 'b', 'a', 'b']

    )r   from_iterabler   tuplerS   rR   rL   rL   rM   r%     s   r%   c                 C   s   t ttj| |S )zcReturns the dot product of the two iterables.

    >>> dotproduct([10, 10], [20, 20])
    400

    )rc   rT   operatormul)vec1vec2rL   rL   rM   r     s   r   c                 C   s
   t | S )zReturn an iterator flattening one level of nesting in a list of lists.

        >>> list(flatten([[0, 1], [2, 3]]))
        [0, 1, 2, 3]

    See also :func:`collapse`, which can flatten multiple levels of nesting.

    )r   rf   )listOfListsrL   rL   rM   r     s   
	r   c                 G   s&   |du rt | t|S t | t||S )aG  Call *func* with *args* repeatedly, returning an iterable over the
    results.

    If *times* is specified, the iterable will terminate after that many
    repetitions:

        >>> from operator import add
        >>> times = 4
        >>> args = 3, 5
        >>> list(repeatfunc(add, times, *args))
        [8, 8, 8, 8]

    If *times* is ``None`` the iterable will not terminate:

        >>> from random import randrange
        >>> times = None
        >>> args = 1, 11
        >>> take(6, repeatfunc(randrange, times, *args))  # doctest:+SKIP
        [2, 4, 8, 1, 8, 4]

    N)r   r   )functimesargsrL   rL   rM   r7   "  s   r7   c                 C   s    t | \}}t|d t||S )zReturns an iterator of paired items, overlapping, from the original

    >>> take(4, pairwise(count()))
    [(0, 1), (1, 2), (2, 3), (3, 4)]

    On Python 3.10 and above, this is an alias for :func:`itertools.pairwise`.

    Nr   r]   zip)rS   abrL   rL   rM   	_pairwise=  s   	

ru   )r*   c                 C   s   t | S rI   )itertools_pairwisere   rL   rL   rM   r*   Q  s   r*   c                       s   e Zd Zd fdd	Z  ZS )UnequalIterablesErrorNc                    s*   d}|d ur|dj | 7 }t | d S )Nz Iterables have different lengthsz/: index 0 has length {}; index {} has length {})formatsuper__init__)selfdetailsmsg	__class__rL   rM   rz   X  s   zUnequalIterablesError.__init__rI   )__name__
__module____qualname__rz   __classcell__rL   rL   r~   rM   rw   W  s    rw   c                 c   s8    t | dtiD ]}|D ]	}|tu rt q|V  qd S )N	fillvalue)r   _markerrw   )	iterablescombovalrL   rL   rM   _zip_equal_generatorb  s   r   c                  G   sn   z)t | d }t| dd  dD ]\}}t |}||kr$t|||fdqt|  W S  ty6   t|  Y S w )Nr      )r|   )r[   	enumeraterw   rr   	TypeErrorr   )r   
first_sizeiitsizerL   rL   rM   
_zip_equalj  s   
r   fillc                 C   sL   t | g| }|dkrt|d|iS |dkrt| S |dkr"t| S td)a  Group elements from *iterable* into fixed-length groups of length *n*.

    >>> list(grouper('ABCDEF', 3))
    [('A', 'B', 'C'), ('D', 'E', 'F')]

    The keyword arguments *incomplete* and *fillvalue* control what happens for
    iterables whose length is not a multiple of *n*.

    When *incomplete* is `'fill'`, the last group will contain instances of
    *fillvalue*.

    >>> list(grouper('ABCDEFG', 3, incomplete='fill', fillvalue='x'))
    [('A', 'B', 'C'), ('D', 'E', 'F'), ('G', 'x', 'x')]

    When *incomplete* is `'ignore'`, the last group will not be emitted.

    >>> list(grouper('ABCDEFG', 3, incomplete='ignore', fillvalue='x'))
    [('A', 'B', 'C'), ('D', 'E', 'F')]

    When *incomplete* is `'strict'`, a subclass of `ValueError` will be raised.

    >>> it = grouper('ABCDEFG', 3, incomplete='strict')
    >>> list(it)  # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    ...
    UnequalIterablesError

    r   r   rG   ignorez Expected fill, strict, or ignore)r\   r   r   rr   
ValueError)rS   rR   
incompleter   rp   rL   rL   rM   r   z  s   r   c                  g   sD    t t| }tt| ddD ]}tt||}t t|E dH  qdS )aJ  Yields an item from each iterable, alternating between them.

        >>> list(roundrobin('ABC', 'D', 'EF'))
        ['A', 'D', 'E', 'B', 'F', 'C']

    This function produces the same output as :func:`interleave_longest`, but
    may perform better for some inputs (in particular when the number of
    iterables is small).

    r   N)rT   r\   ranger[   r
   r   r]   )r   	iterators
num_activerL   rL   rM   r8     s   
r8   c                 C   sJ   | du rt } t|d\}}}tt| |\}}t|ttj|t||fS )a  
    Returns a 2-tuple of iterables derived from the input iterable.
    The first yields the items that have ``pred(item) == False``.
    The second yields the items that have ``pred(item) == True``.

        >>> is_odd = lambda x: x % 2 != 0
        >>> iterable = range(10)
        >>> even_items, odd_items = partition(is_odd, iterable)
        >>> list(even_items), list(odd_items)
        ([0, 2, 4, 6, 8], [1, 3, 5, 7, 9])

    If *pred* is None, :func:`bool` is used.

        >>> iterable = [0, 1, False, True, '', ' ']
        >>> false_items, true_items = partition(None, iterable)
        >>> list(false_items), list(true_items)
        ([0, False, ''], [1, True, ' '])

    N   )boolr   rT   r   ri   not_)rd   rS   t1t2pp1p2rL   rL   rM   r+     s
   r+   c                    s,   t |  t fddtt d D S )a1  Yields all possible subsets of the iterable.

        >>> list(powerset([1, 2, 3]))
        [(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]

    :func:`powerset` will operate on iterables that aren't :class:`set`
    instances, so repeated elements in the input will produce repeated elements
    in the output.

        >>> seq = [1, 1, 0]
        >>> list(powerset(seq))
        [(), (1,), (1,), (0,), (1, 1), (1, 0), (1, 0), (1, 1, 0)]

    For a variant that efficiently yields actual :class:`set` instances, see
    :func:`powerset_of_sets`.
    c                 3       | ]}t  |V  qd S rI   )r   ).0rsrL   rM   	<genexpr>      zpowerset.<locals>.<genexpr>r   )rP   r   rf   r   r[   re   rL   r   rM   r/     s   $r/   c           	   	   c   s    t  }|j}g }|j}|du}| D ]+}|r||n|}z||vr(|| |V  W q ty=   ||vr;|| |V  Y qw dS )a  
    Yield unique elements, preserving order.

        >>> list(unique_everseen('AAAABBBCCDAABBB'))
        ['A', 'B', 'C', 'D']
        >>> list(unique_everseen('ABBCcAD', str.lower))
        ['A', 'B', 'C', 'D']

    Sequences with a mix of hashable and unhashable items can be used.
    The function will be slower (i.e., `O(n^2)`) for unhashable items.

    Remember that ``list`` objects are unhashable - you can use the *key*
    parameter to transform the list to a tuple (which is hashable) to
    avoid a slowdown.

        >>> iterable = ([1, 2], [2, 3], [1, 2])
        >>> list(unique_everseen(iterable))  # Slow
        [[1, 2], [2, 3]]
        >>> list(unique_everseen(iterable, key=tuple))  # Faster
        [[1, 2], [2, 3]]

    Similarly, you may want to convert unhashable ``set`` objects with
    ``key=frozenset``. For ``dict`` objects,
    ``key=lambda x: frozenset(x.items())`` can be used.

    N)setaddappendr   )	rS   r`   seensetseenset_addseenlistseenlist_adduse_keyelementkrL   rL   rM   rD     s(   rD   c                 C   s8   |du rt tdt| S t tt tdt| |S )zYields elements in order, ignoring serial duplicates

    >>> list(unique_justseen('AAAABBBCCDAABBB'))
    ['A', 'B', 'C', 'D', 'A', 'B']
    >>> list(unique_justseen('ABBCcAD', str.lower))
    ['A', 'B', 'C', 'A', 'D']

    Nr   r   )rT   ri   
itemgetterr   r]   )rS   r`   rL   rL   rM   rE     s   	rE   Fc                 C   s   t t| ||d|dS )a  Yields unique elements in sorted order.

    >>> list(unique([[1, 2], [3, 4], [1, 2]]))
    [[1, 2], [3, 4]]

    *key* and *reverse* are passed to :func:`sorted`.

    >>> list(unique('ABBcCAD', str.casefold))
    ['A', 'B', 'c', 'D']
    >>> list(unique('ABBcCAD', str.casefold, reverse=True))
    ['D', 'c', 'B', 'A']

    The elements in *iterable* need not be hashable, but they must be
    comparable for sorting to work.
    )r`   reverse)r`   )rE   sorted)rS   r`   r   rL   rL   rM   rC   !  s   rC   c                 c   s4    z|dur
| V  	 |  V  q |y   Y dS w )a  Yields results from a function repeatedly until an exception is raised.

    Converts a call-until-exception interface to an iterator interface.
    Like ``iter(func, sentinel)``, but uses an exception instead of a sentinel
    to end the loop.

        >>> l = [0, 1, 2]
        >>> list(iter_except(l.pop, IndexError))
        [2, 1, 0]

    Multiple exceptions can be specified as a stopping condition:

        >>> l = [1, 2, 3, '...', 4, 5, 6]
        >>> list(iter_except(lambda: 1 + l.pop(), (IndexError, TypeError)))
        [7, 6, 5]
        >>> list(iter_except(lambda: 1 + l.pop(), (IndexError, TypeError)))
        [4, 3, 2]
        >>> list(iter_except(lambda: 1 + l.pop(), (IndexError, TypeError)))
        []

    NrL   )rn   	exceptionra   rL   rL   rM   r!   4  s   r!   c                 C   s   t t|| |S )a  
    Returns the first true value in the iterable.

    If no true value is found, returns *default*

    If *pred* is not None, returns the first item for which
    ``pred(item) == True`` .

        >>> first_true(range(10))
        1
        >>> first_true(range(10), pred=lambda x: x > 5)
        6
        >>> first_true(range(10), default='missing', pred=lambda x: x > 9)
        'missing'

    )r]   filter)rS   r_   rd   rL   rL   rM   r   S  s   r   r   r   c                 G   s$   dd |D |  }t dd |D S )a  Draw an item at random from each of the input iterables.

        >>> random_product('abc', range(4), 'XYZ')  # doctest:+SKIP
        ('c', 3, 'Z')

    If *repeat* is provided as a keyword argument, that many items will be
    drawn from each iterable.

        >>> random_product('abcd', range(4), repeat=2)  # doctest:+SKIP
        ('a', 2, 'd', 3)

    This equivalent to taking a random selection from
    ``itertools.product(*args, **kwarg)``.

    c                 S   s   g | ]}t |qS rL   rg   r   poolrL   rL   rM   
<listcomp>w  s    z"random_product.<locals>.<listcomp>c                 s   s    | ]}t |V  qd S rI   )r   r   rL   rL   rM   r   x      z!random_product.<locals>.<genexpr>r   )r   rp   poolsrL   rL   rM   r6   g  s   r6   c                 C   s*   t | }|du rt|n|}t t||S )ab  Return a random *r* length permutation of the elements in *iterable*.

    If *r* is not specified or is ``None``, then *r* defaults to the length of
    *iterable*.

        >>> random_permutation(range(5))  # doctest:+SKIP
        (3, 4, 0, 1, 2)

    This equivalent to taking a random selection from
    ``itertools.permutations(iterable, r)``.

    N)rg   r[   r   )rS   r   r   rL   rL   rM   r5   {  s   r5   c                    s8   t |  t }ttt||}t  fdd|D S )zReturn a random *r* length subsequence of the elements in *iterable*.

        >>> random_combination(range(5), 3)  # doctest:+SKIP
        (2, 3, 4)

    This equivalent to taking a random selection from
    ``itertools.combinations(iterable, r)``.

    c                 3       | ]} | V  qd S rI   rL   r   r   r   rL   rM   r     r   z%random_combination.<locals>.<genexpr>)rg   r[   r   r   r   )rS   r   rR   indicesrL   r   rM   r4     s   
r4   c                    s@   t | t t fddt|D }t fdd|D S )aS  Return a random *r* length subsequence of elements in *iterable*,
    allowing individual elements to be repeated.

        >>> random_combination_with_replacement(range(3), 5) # doctest:+SKIP
        (0, 0, 1, 2, 2)

    This equivalent to taking a random selection from
    ``itertools.combinations_with_replacement(iterable, r)``.

    c                 3   s    | ]}t  V  qd S rI   r   r   rR   rL   rM   r     r   z6random_combination_with_replacement.<locals>.<genexpr>c                 3   r   rI   rL   r   r   rL   rM   r     r   )rg   r[   r   r   )rS   r   r   rL   )rR   r   rM   r3     s   r3   c           	      C   s   t | }t|}|dk s||krtd}t||| }td|d D ]}||| |  | }q"|dk r7||7 }|dk s?||krAtg }|ry|| | |d |d }}}||krn||8 }|||  | |d }}||ksY||d|   |sEt |S )a  Equivalent to ``list(combinations(iterable, r))[index]``.

    The subsequences of *iterable* that are of length *r* can be ordered
    lexicographically. :func:`nth_combination` computes the subsequence at
    sort position *index* directly, without computing the previous
    subsequences.

        >>> nth_combination(range(5), 3, 5)
        (0, 3, 4)

    ``ValueError`` will be raised If *r* is negative or greater than the length
    of *iterable*.
    ``IndexError`` will be raised if the given *index* is invalid.
    r   r   r   )rg   r[   r   minr   
IndexErrorr   )	rS   r   indexr   rR   cr   r   resultrL   rL   rM   r'     s,    r'   c                 C   s   t | g|S )a  Yield *value*, followed by the elements in *iterator*.

        >>> value = '0'
        >>> iterator = ['1', '2', '3']
        >>> list(prepend(value, iterator))
        ['0', '1', '2', '3']

    To prepend multiple values, see :func:`itertools.chain`
    or :func:`value_chain`.

    )r   )valuer^   rL   rL   rM   r0     s   r0   c                 c   sb    t |ddd }t|}tdg|d| }t| td|d D ]}|| t||V  q!dS )aB  Convolve the iterable *signal* with the iterable *kernel*.

        >>> signal = (1, 2, 3, 4, 5)
        >>> kernel = [3, 2, 1]
        >>> list(convolve(signal, kernel))
        [3, 8, 14, 20, 26, 14, 5]

    Note: the input arguments are not interchangeable, as the *kernel*
    is immediately consumed and stored.

    Nr   r   rW   r   )rg   r[   r   r   r   r   _sumprod)signalkernelrR   windowrJ   rL   rL   rM   r     s   
r   c                    s0   t   g  fdd}t }| |fS )a  A variant of :func:`takewhile` that allows complete access to the
    remainder of the iterator.

         >>> it = iter('ABCdEfGhI')
         >>> all_upper, remainder = before_and_after(str.isupper, it)
         >>> ''.join(all_upper)
         'ABC'
         >>> ''.join(remainder) # takewhile() would lose the 'd'
         'dEfGhI'

    Note that the first iterator must be fully consumed before the second
    iterator can generate valid results.
    c                  3   s.     D ]} | r| V  q |   d S d S rI   )r   )elemr   	predicate
transitionrL   rM   true_iterator  s   
z'before_and_after.<locals>.true_iterator)r\   r   )r   r   r   remainder_iteratorrL   r   rM   r     s
   

r   c                 C   s:   t | d\}}}t|d t|d t|d t|||S )zReturn overlapping triplets from *iterable*.

    >>> list(triplewise('ABCDE'))
    [('A', 'B', 'C'), ('B', 'C', 'D'), ('C', 'D', 'E')]

    r   Nrq   )rS   r   r   t3rL   rL   rM   rB     s
   	


rB   c                 C   s6   t | |}t|D ]\}}tt|||d  q	t| S rI   )r   r   r]   r   rr   )rS   rR   r   r   r^   rL   rL   rM   _sliding_window_islice.  s   
r   c                 c   sB    t | }tt||d |d}|D ]}|| t|V  qd S )Nr   rW   )r\   r   r   r   rg   )rS   rR   r   r   rJ   rL   rL   rM   _sliding_window_deque6  s   
r   c                 C   sR   |dkr	t | |S |dkrt| |S |dkrt| S |dkr"t| S td| )aY  Return a sliding window of width *n* over *iterable*.

        >>> list(sliding_window(range(6), 4))
        [(0, 1, 2, 3), (1, 2, 3, 4), (2, 3, 4, 5)]

    If *iterable* has fewer than *n* items, then nothing is yielded:

        >>> list(sliding_window(range(3), 4))
        []

    For a variant with more features, see :func:`windowed`.
          r   zn should be at least one, not )r   r   r*   rr   r   rh   rL   rL   rM   r:   ?  s   

r:   c                 C   s6   t | }ttttt|d d}ttjt	||S )zReturn all contiguous non-empty subslices of *iterable*.

        >>> list(subslices('ABC'))
        [['A'], ['A', 'B'], ['A', 'B', 'C'], ['B'], ['B', 'C'], ['C']]

    This is similar to :func:`substrings`, but emits items in a different
    order.
    r   r   )
rP   r   slicer   r   r[   rT   ri   getitemr   )rS   seqslicesrL   rL   rM   r;   X  s   	r;   c                 C   s(   dg}| D ]}t t|d| f}q|S )zCompute a polynomial's coefficients from its roots.

    >>> roots = [5, -4, 3]  # (x - 5) * (x + 4) * (x - 3)
    >>> polynomial_from_roots(roots)  # x^3 - 4 * x^2 - 17 * x + 60
    [1, -4, -17, 60]
    r   )rP   r   )rootspolyrootrL   rL   rM   r-   f  s   r-   c                 c   s    t | dd}|du r(t| ||}t||D ]\}}||u s"||kr%|V  qdS |du r0t| n|}|d }z	 |||d | }V  q8 tyM   Y dS w )a  Yield the index of each place in *iterable* that *value* occurs,
    beginning with index *start* and ending before index *stop*.


    >>> list(iter_index('AABCADEAF', 'A'))
    [0, 1, 4, 7]
    >>> list(iter_index('AABCADEAF', 'A', 1))  # start index is inclusive
    [1, 4, 7]
    >>> list(iter_index('AABCADEAF', 'A', 1, 7))  # stop index is not inclusive
    [1, 4]

    The behavior for non-scalar *values* matches the built-in Python types.

    >>> list(iter_index('ABCDABCD', 'AB'))
    [0, 4]
    >>> list(iter_index([0, 1, 2, 3, 0, 1, 2, 3], [0, 1]))
    []
    >>> list(iter_index([[0, 1], [2, 3], [0, 1], [2, 3]], [0, 1]))
    [0, 2]

    See :func:`locate` for a more general means of finding the indexes
    associated with particular values.

    r   Nr   )getattrr   r   r[   r   )rS   r   rV   stop	seq_indexr   r   r   rL   rL   rM   r"   s  s$   r"   c                 c   s    | dkrdV  d}t d| d  }t| d }t|d||D ])}t|d||| E dH  ttt|| | || ||| | || < || }q t|d|E dH  dS )zdYield the primes less than n.

    >>> list(sieve(30))
    [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
    r   r   )r   r   r   N)	bytearraymathisqrtr"   bytesr[   r   )rR   rV   datalimitr   rL   rL   rM   r9     s   .
r9   c                c   sd    |dk r	t dt| }tt|| }r0|r"t||kr"t d|V  tt|| }sdS dS )a  Batch data into tuples of length *n*. If the number of items in
    *iterable* is not divisible by *n*:
    * The last batch will be shorter if *strict* is ``False``.
    * :exc:`ValueError` will be raised if *strict* is ``True``.

    >>> list(batched('ABCDEFG', 3))
    [('A', 'B', 'C'), ('D', 'E', 'F'), ('G',)]

    On Python 3.13 and above, this is an alias for :func:`itertools.batched`.
    r   zn must be at least onezbatched(): incomplete batchN)r   r\   rg   r   r[   )rS   rR   rG   r   batchrL   rL   rM   _batched  s   r   i )r   c                C   s   t | ||dS )NrF   )itertools_batched)rS   rR   rG   rL   rL   rM   r     s   r   c                 C   s   t |  S )a  Swap the rows and columns of the input matrix.

    >>> list(transpose([(1, 2, 3), (11, 22, 33)]))
    [(1, 11), (2, 22), (3, 33)]

    The caller should ensure that the dimensions of the input are compatible.
    If the input is empty, no output will be produced.
    )_zip_strictr   rL   rL   rM   rA     s   	rA   c                 C   s   t t| |S )zReshape the 2-D input *matrix* to have a column count given by *cols*.

    >>> matrix = [(0, 1), (2, 3), (4, 5)]
    >>> cols = 3
    >>> list(reshape(matrix, cols))
    [(0, 1, 2), (3, 4, 5)]
    )r   r   rf   )matrixcolsrL   rL   rM   r2     s   r2   c                 C   s&   t |d }tttt| t||S )zMultiply two matrices.

    >>> list(matmul([(7, 5), (3, 5)], [(2, 5), (7, 9)]))
    [(49, 80), (41, 60)]

    The caller should ensure that the dimensions of the input matrices are
    compatible with each other.
    r   )r[   r   r   r   r   rA   )m1m2rR   rL   rL   rM   r$     s   	r$   c                 C   s   t j}td| d D ]7}d }}d}|dkr9|| | |  }|| | |  }|| | |  }||| | }|dks|| krA|  S q
td)Nr   r   zprime or under 5)r   gcdr   r   )rR   r   rt   rJ   rK   drL   rL   rM   _factor_pollard  s   r      c                 c   s    | dk rdS t D ]}| | s|V  | | } | | rq	g }| dkr$| gng }|D ]} | dk s2t| r8||  q(t| }||| | f7 }q(t|E dH  dS )a  Yield the prime factors of n.

    >>> list(factor(360))
    [2, 2, 2, 3, 3, 5]

    Finds small factors with trial division.  Larger factors are
    either verified as prime with ``is_prime`` or split into
    smaller factors with Pollard's rho algorithm.
    r   Nr   i  )_primes_below_211r    r   r   r   )rR   primeprimestodofactrL   rL   rM   r     s"   r   c                 C   s:   t | }|dkr|d S ttt|tt|}t| |S )zEvaluate a polynomial at a specific value.

    Example: evaluating x^3 - 4 * x^2 - 17 * x + 60 at x = 2.5:

    >>> coefficients = [1, -4, -17, 60]
    >>> x = 2.5
    >>> polynomial_eval(coefficients, x)
    8.125
    r   )r[   rT   powr   reversedr   r   )coefficientsrJ   rR   powersrL   rL   rM   r,   (  s
   

r,   c                 C   s   t t|  S )zfReturn the sum of the squares of the input values.

    >>> sum_of_squares([10, 20, 30])
    1400
    )r   r   r   rL   rL   rM   r<   9  s   r<   c                 C   s(   t | }ttd|}tttj| |S )a  Compute the first derivative of a polynomial.

    Example: evaluating the derivative of x^3 - 4 * x^2 - 17 * x + 60

    >>> coefficients = [1, -4, -17, 60]
    >>> derivative_coefficients = polynomial_derivative(coefficients)
    >>> derivative_coefficients
    [3, -8, -17]
    r   )r[   r   r   rP   rT   ri   rj   )r   rR   r   rL   rL   rM   r.   B  s   
r.   c                 C   s"   t t| D ]}| | | 8 } q| S )zReturn the count of natural numbers up to *n* that are coprime with *n*.

    >>> totient(9)
    6
    >>> totient(12)
    4
    )r   r   )rR   r   rL   rL   rM   r@   Q  s   r@   ))i  )r   )i )   I   )l   tT7 )r      =   )l   ay)r         iS_ )l   ;n>)r   r      r     )l   p)r   r   r  r  r  r  )l            )r   iE  i$  in  i i= ik)l   %!HnfW )r   r   r  r  r  r        r     r   %   )   c                 C   sH   | d | A   d }| |? }d|> | | kr|d@ r|dks J ||fS )z#Return s, d such that 2**s * d == nr   r   )
bit_length)rR   r   r   rL   rL   rM   _shift_to_oddn  s   $r  c                 C   s   | dkr| d@ rd|  kr| k sJ  J t | d \}}t||| }|dks.|| d kr0dS t|d D ]}|| |  }|| d krG dS q6dS )Nr   r   TF)r  r   r   )rR   baser   r   rJ   _rL   rL   rM   _strong_probable_primew  s   ,r  c                    s    dk r dv S  d@ r  d r  d r  d r  d r  d s"d	S t D ]
\}} |k r. nq$ fd
dtdD }t fdd|D S )a  Return ``True`` if *n* is prime and ``False`` otherwise.

    >>> is_prime(37)
    True
    >>> is_prime(3 * 13)
    False
    >>> is_prime(18_446_744_073_709_551_557)
    True

    This function uses the Miller-Rabin primality test, which can return false
    positives for very large inputs. For values of *n* below 10**24
    there are no false positives. For larger values, there is less than
    a 1 in 2**128 false positive rate. Multiple tests can further reduce the
    chance of a false positive.
    r  >   r   r   r  r  r  r  r   r   r  r  r  r  Fc                    s   g | ]	}t d  d qS )r   r   r   r   r   rL   rM   r     s    zis_prime.<locals>.<listcomp>@   c                 3   r   rI   )r  )r   r  r   rL   rM   r     r   zis_prime.<locals>.<genexpr>)_perfect_testsr   all)rR   r   basesrL   r   rM   r      s   0r    c                 C   s
   t d| S )zReturns an iterable with *n* elements for efficient looping.
    Like ``range(n)`` but doesn't create integers.

    >>> i = 0
    >>> for _ in loops(5):
    ...     i += 1
    >>> i
    5

    Nr   r   rL   rL   rM   r#     s   
r#   )r   rI   )r   N)NF)NN)r   N)g__doc__r   ri   collectionsr   collections.abcr   	functoolsr   r   	itertoolsr   r   r   r	   r
   r   r   r   r   r   r   r   randomr   r   r   sysr   __all__objectr   rr   r   r   r   r   r?   r=   r>   r   r&   r   r   r1   r)   r(   r%   r   r   r7   ru   r*   rv   ImportErrorr   rw   r   r   r   r8   r+   r/   rD   rE   rC   r!   r   r6   r5   r4   r3   r'   r0   r   r   rB   r   r   r:   r;   r-   r"   r9   r   r   r   rA   r2   r$   r   rg   r   r   r,   r<   r.   r@   r  r  r  r    r#   rL   rL   rL   rM   <module>   s    
83


(





(

-



*!	
+
!	
