U
    hr                  .   @   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 d	d
dddddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5d6g.Ze Zze d7d8 W n e!k
r"   e Z"Y nX ee d7d8Z"e#ed9d:d; Z$d<d0 Z%d~d=d.Z&d>d/ Z'dd?dZ(dd@dZ)ddAd	Z*e+fdBd"Z,dCd Z-e-Z.dDd Z/dEd Z0dFd Z1ddGd(Z2dHdI Z3zddJl
m4Z5 W n e6k
r   e3Z4Y nX dKd Z4e3j e4_ G dLdM dMe7Z8dNdO Z9dPdQ Z:ddSdZ;dTd) Z<dUd Z=dVd  Z>ddWd5Z?ddXd6Z@ddZd4ZAdd[dZBdd\dZCd]d^d_d'ZDdd`d&ZEdad% ZFdbd$ ZGdcd ZHddd! ZIded ZJdfd ZKdgd3 ZLdhdi ZMdjdk ZNdld+ ZOdmd, ZPdnd ZQddodZRdpd* ZSdYd8dqdrZTedskr(ddtl
mUZV dYd8dud
ZUneTZUeTj eU_ dvd2 ZWdwd# ZXdxd ZYdyd ZZdzd Z[d{d- Z\d|d Z]d}d1 Z^d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)partialreduce)chaincombinationscompresscountcyclegroupbyisliceproductrepeatstarmapteezip_longest)	randrangesamplechoice)
hexversion	all_equalbatchedbefore_and_afterconsumeconvolve
dotproduct
first_truefactorflattengrouperiter_except
iter_index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strictZsumprodc                 C   s
   t | |S N)r   )xy rI   H/var/www/html/venv/lib/python3.8/site-packages/more_itertools/recipes.py<lambda>_       rK   c                 C   s   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iterablerI   rI   rJ   r=   b   s    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startrI   rI   rJ   r;   r   s    c                 c   sF   t |tr,t|tdt||  dE dH  n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   rN   rI   rI   rJ   r<      s    
"c                 C   s,   |dkrt | dd n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   rT   )r   nextr   )iteratorrO   rI   rI   rJ   r      s     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)rZ   r   )rP   rO   defaultrI   rI   rJ   r$      s    
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   )rP   keyr[   firstsecondrI   rI   rJ   r      s    
c                 C   s   t t|| S )zcReturn the how many times the predicate is true.

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

    )sumrQ   )rP   predrI   rI   rJ   r/      s    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   rP   rI   rI   rJ   r'      s    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rP   rO   rI   rI   rJ   r#      s    c                 C   s   t ttj| |S )zcReturns the dot product of the two iterables.

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

    )r`   rQ   operatormul)Zvec1Zvec2rI   rI   rJ   r   
  s    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   rc   )ZlistOfListsrI   rI   rJ   r     s    	c                 G   s&   |dk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argsrI   rI   rJ   r5      s    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   rZ   zip)rP   abrI   rI   rJ   	_pairwise;  s    	
ro   )r(   c                 C   s   t | S rF   )itertools_pairwiserb   rI   rI   rJ   r(   O  s    c                       s   e Zd Zd fdd	Z  ZS )UnequalIterablesErrorNc                    s*   d}|d k	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__rI   rJ   rt   V  s    zUnequalIterablesError.__init__)N)__name__
__module____qualname__rt   __classcell__rI   rI   rx   rJ   rq   U  s   rq   c                 c   s6   t | dtiD ]"}|D ]}|tkrt q|V  qd S )N	fillvalue)r   _markerrq   )	iterablesZcombovalrI   rI   rJ   _zip_equal_generator`  s
    r   c                  G   st   zRt | d }t| dd  dD ](\}}t |}||kr t|||fdq t|  W S  tk
rn   t|  Y S X d S )Nr      )rv   )rX   	enumeraterq   rl   	TypeErrorr   )r   Z
first_sizeiitsizerI   rI   rJ   
_zip_equalh  s    
r   fillc                 C   sP   t | g| }|dkr$t|d|iS |dkr4t| S |dkrDt| S tddS )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~   rE   ignorez Expected fill, strict, or ignoreN)rY   r   r   rl   
ValueError)rP   rO   
incompleter~   rj   rI   rI   rJ   r   x  s    c                  g   sB   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)rQ   rY   rangerX   r
   r   rZ   )r   	iteratorsZ
num_activerI   rI   rJ   r6     s    
c                 C   sJ   | dk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   rQ   r   rf   not_)ra   rP   t1t2pp1Zp2rI   rI   rJ   r)     s
    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   s   | ]}t  |V  qd S rF   )r   ).0rsrI   rJ   	<genexpr>  s     zpowerset.<locals>.<genexpr>r   )rM   r   rc   r   rX   rb   rI   r   rJ   r-     s    c           	   	   c   s   t  }|j}g }|j}|dk	}| D ]Z}|r2||n|}z||krN|| |V  W q" tk
rz   ||krv|| |V  Y q"X q"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   )	rP   r]   ZseensetZseenset_addZseenlistZseenlist_addZuse_keyelementkrI   rI   rJ   rB     s    
c                 C   s8   |dk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   )rQ   rf   
itemgetterr   rZ   )rP   r]   rI   rI   rJ   rC     s    	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]   )rC   sorted)rP   r]   r   rI   rI   rJ   rA     s    c                 c   s8   z|dk	r| V  |  V  qW n |k
r2   Y nX dS )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)))
        []

    NrI   )rh   	exceptionr^   rI   rI   rJ   r    2  s    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'

    )rZ   filter)rP   r\   ra   rI   rI   rJ   r   Q  s    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 rI   rd   r   poolrI   rI   rJ   
<listcomp>u  s     z"random_product.<locals>.<listcomp>c                 s   s   | ]}t |V  qd S rF   )r   r   rI   rI   rJ   r   v  s     z!random_product.<locals>.<genexpr>r   )r   rj   poolsrI   rI   rJ   r4   e  s    c                 C   s*   t | }|dk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)rd   rX   r   )rP   r   r   rI   rI   rJ   r3   y  s    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   s   | ]} | V  qd S rF   rI   r   r   r   rI   rJ   r     s     z%random_combination.<locals>.<genexpr>)rd   rX   r   r   r   )rP   r   rO   indicesrI   r   rJ   r2     s    
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 rF   )r   r   )rO   rI   rJ   r     s     z6random_combination_with_replacement.<locals>.<genexpr>c                 3   s   | ]} | V  qd S rF   rI   r   r   rI   rJ   r     s     )rd   rX   r   r   )rP   r   r   rI   )rO   r   rJ   r1     s    c           	      C   s   t | }t|}|dk s ||kr$td}t||| }td|d D ]}||| |  | }qD|dk rn||7 }|dk s~||krtg }|r|| | |d |d   }}}||kr||8 }|||  | |d  }}q||d|   qt |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   )rd   rX   r   minr   
IndexErrorr   )	rP   r   indexr   rO   cr   r   resultrI   rI   rJ   r%     s(     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[   rI   rI   rJ   r.     s    c                 c   s`   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   rT   r   )rd   rX   r   r   r   r   _sumprod)signalZkernelrO   windowrG   rI   rI   rJ   r     s    
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 qd S rF   )r   )elemr   	predicateZ
transitionrI   rJ   true_iterator  s
    
z'before_and_after.<locals>.true_iterator)rY   r   )r   r   r   Zremainder_iteratorrI   r   rJ   r     s
    
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   Nrk   )rP   r   r   Zt3rI   rI   rJ   r@     s
    	


c                 C   s6   t | |}t|D ]\}}tt|||d  qt| S rF   )r   r   rZ   r   rl   )rP   rO   r   r   r[   rI   rI   rJ   _sliding_window_islice,  s    
r   c                 c   s@   t | }tt||d |d}|D ]}|| t|V  q"d S )Nr   rT   )rY   r   r   r   rd   )rP   rO   r   r   rG   rI   rI   rJ   _sliding_window_deque4  s
    
r   c                 C   sV   |dkrt | |S |dkr$t| |S |dkr4t| S |dkrDt| S td| dS )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 N)r   r   r(   rl   r   re   rI   rI   rJ   r8   =  s    

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   )
rM   r   slicer   r   rX   rQ   rf   getitemr   )rP   seqZslicesrI   rI   rJ   r9   V  s    	c                 C   s(   t tdttj| }ttt|dg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   )rl   r   rQ   rf   negrM   r   r   )rootsZfactorsrI   rI   rJ   r+   d  s    c                 c   s   t | dd}|dkrLt| ||}t||D ]\}}||ksB||kr*|V  q*nN|dkr\t| n|}|d }z|||d | }V  qjW n tk
r   Y nX dS )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   rX   r   )rP   r   rS   stopZ	seq_indexr   r   r   rI   rI   rJ   r!   o  s    
c                 c   s   | dkrdV  d}t d| d  }t| d }t|d||D ]R}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!   bytesrX   r   )rO   rS   datalimitr   rI   rI   rJ   r7     s    .
c                c   sN   |dk rt dt| }tt|| }rJ|rBt||krBt d|V  q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   rY   rd   r   rX   )rP   rO   rE   r   batchrI   rI   rJ   _batched  s    r   i )r   c                C   s   t | ||dS )NrD   )itertools_batched)rP   rO   rE   rI   rI   rJ   r     s    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   rI   rI   rJ   r?     s    	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   rc   )matrixcolsrI   rI   rJ   r0     s    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   )rX   r   r   r   r   r?   )m1m2rO   rI   rI   rJ   r"     s    	c                 c   sP   t t| d D ]*}| | s|V  | | } | dkr dS qq| dkrL| V  dS )zTYield the prime factors of n.

    >>> list(factor(360))
    [2, 2, 2, 3, 3, 5]
    r   N)r7   r   r   rO   primerI   rI   rJ   r     s    
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   )rX   rQ   powr   reversedr   r   )coefficientsrG   rO   powersrI   rI   rJ   r*      s
    
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   rI   rI   rJ   r:     s    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   )rX   r   r   rM   rQ   rf   rg   )r   rO   r   rI   rI   rJ   r,     s    
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   r   rI   rI   rJ   r>   )  s    )r   )N)N)N)N)r   N)N)N)NF)N)NN)N)r   N)___doc__r   rf   collectionsr   collections.abcr   	functoolsr   r   	itertoolsr   r   r   r	   r
   r   r   r   r   r   r   r   randomr   r   r   sysr   __all__objectr   rl   r   r   r   r   r=   r;   r<   r   r$   r   r   r/   r'   r&   r#   r   r   r5   ro   r(   rp   ImportErrorr   rq   r   r   r   r6   r)   r-   rB   rC   rA   r    r   r4   r3   r2   r1   r%   r.   r   r   r@   r   r   r8   r9   r+   r!   r7   r   r   r   r?   r0   r"   r   r*   r:   r,   r>   rI   rI   rI   rJ   <module>   s   
81


(







(
-




*!	
+
	