B
    [                 @   s^   d dl mZmZ d dlmZ d dlmZ dd Zdd Ze	e
fdd	Zd
d Ze	fddZdS )    )print_functiondivision)defaultdict)rangec             C   sl   d| fd| dfdi}d}xNt d| d d D ]8}|| | d  | }| ||| | f< || | |f< q,W |S )a  Return a dictionary containing pairs :math:`{(k1,k2) : C_kn}` where
    :math:`C_kn` are binomial coefficients and :math:`n=k1+k2`.
    Examples
    ========

    >>> from sympy.ntheory import binomial_coefficients
    >>> binomial_coefficients(9)
    {(0, 9): 1, (1, 8): 9, (2, 7): 36, (3, 6): 84,
     (4, 5): 126, (5, 4): 126, (6, 3): 84, (7, 2): 36, (8, 1): 9, (9, 0): 1}

    See Also
    ========

    binomial_coefficients_list, multinomial_coefficients
    r         )r   )ndak r   8lib/python3.7/site-packages/sympy/ntheory/multinomial.pybinomial_coefficients   s    $r   c             C   sZ   dg| d  }d}xBt d| d d D ],}|| | d  | }| ||< || | < q&W |S )aL   Return a list of binomial coefficients as rows of the Pascal's
    triangle.

    Examples
    ========

    >>> from sympy.ntheory import binomial_coefficients_list
    >>> binomial_coefficients_list(9)
    [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]

    See Also
    ========

    binomial_coefficients, multinomial_coefficients
    r   r   )r   )r   r	   r
   r   r   r   r   binomial_coefficients_list   s    r   c                sx  sri S ddiS dkr$t S fddtD }|d  fdd|D } fdd	D di}dgd  d  }| |d< xtdd  d D ]ĉtt}xtdtd D ]v}	d |	  }
|
sq||	 }xR||	  D ]B\}} d
d ||D }||  |
| 7  < || s||= qW qW fdd| D }||< || qW |S )ae  Return a dictionary containing pairs ``{(k1,k2,..,km) : C_kn}``
    where ``C_kn`` are multinomial coefficients such that
    ``n=k1+k2+..+km``.

    For example:

    >>> from sympy import multinomial_coefficients
    >>> multinomial_coefficients(2, 5) # indirect doctest
    {(0, 5): 1, (1, 4): 5, (2, 3): 10, (3, 2): 10, (4, 1): 5, (5, 0): 1}

    The algorithm is based on the following result:

       Consider a polynomial and its ``n``-th exponent::

         P(x) = sum_{i=0}^m p_i x^i
         P(x)^n = sum_{k=0}^{m n} a(n,k) x^k

       The coefficients ``a(n,k)`` can be computed using the
       J.C.P. Miller Pure Recurrence [see D.E.Knuth, Seminumerical
       Algorithms, The art of Computer Programming v.2, Addison
       Wesley, Reading, 1981;]::

         a(n,k) = 1/(k p_0) sum_{i=1}^m p_i ((n+1)i-k) a(n,k-i),

       where ``a(n,0) = p_0^n``.
    r   r   r   c                s(   g | ] }d | d d  | d   qS ))r   )r   r   r   ).0i)mr   r   
<listcomp>Y   s    z-multinomial_coefficients0.<locals>.<listcomp>r   c                s$   g | ]} d d |D qS )c             s   s   | ]\}}|| V  qd S )Nr   )r   aabbr   r   r   	<genexpr>[   s    z7multinomial_coefficients0.<locals>.<listcomp>.<genexpr>r   )r   s)_tuple_zips0r   r   r   [   s    c             3   s   | ]}|  V  qd S )Nr   )r   r   )r   r   r   r   \   s    z,multinomial_coefficients0.<locals>.<genexpr>c             S   s   g | ]\}}|| qS r   r   )r   r   r   r   r   r   r   g   s    c                s   g | ]\}}||  fqS r   r   )r   tc)r   r   r   r   k   s    )r   r   itemsr   intminupdate)r   r   r   r   ZsymbolsZp0rlr	   r   Znnr   Zt2Zc2ZttZr1r   )r   r   r   r   r   r   r   multinomial_coefficients07   s8    r#   c       	      C   s|  | s|ri S ddiS | dkr$t |S | d| krF|dkrFtt| |S |gdg| d   }t|di}|rpd}n| }x || d k rv|| }|rd||< ||d< |dkr||d   d7  < d}d}d}n,|d7 }|d }|t| }||  d7  < xNt|| D ]@}|| r||  d8  < ||t| 7 }||  d7  < qW |d  d8  < || ||d   |t|< qxW |S )a  Return a dictionary containing pairs ``{(k1,k2,..,km) : C_kn}``
    where ``C_kn`` are multinomial coefficients such that
    ``n=k1+k2+..+km``.

    For example:

    >>> from sympy.ntheory import multinomial_coefficients
    >>> multinomial_coefficients(2, 5) # indirect doctest
    {(0, 5): 1, (1, 4): 5, (2, 3): 10, (3, 2): 10, (4, 1): 5, (5, 0): 1}

    The algorithm is based on the following result:

    .. math::
        \binom{n}{k_1, \ldots, k_m} =
        \frac{k_1 + 1}{n - k_1} \sum_{i=2}^m \binom{n}{k_1 + 1, \ldots, k_i - 1, \ldots}

    Code contributed to Sage by Yann Laigle-Chapuy, copied with permission
    of the author.

    See Also
    ========

    binomial_coefficients_list, binomial_coefficients
    r   r   r   r   )r   dict!multinomial_coefficients_iteratortupler   )	r   r   r   r!   jtjstartvr   r   r   r   multinomial_coefficientsq   sF    
 r+   c             c   sf  | d| k s|dkrBt | |}x| D ]\}}||fV  q(W n t ||}i }x&| D ]\}}|||td|< qZW |}|gdg| d   }||}|td|}	|||	 fV  |rd}
n| }
x|
| d k r`||
 }|
rd||
< ||d< |dkr||
d   d7  < d}
n|
d7 }
||
  d7  < |d  d8  < ||}|td|}	|||	 fV  qW dS )aq  multinomial coefficient iterator

    This routine has been optimized for `m` large with respect to `n` by taking
    advantage of the fact that when the monomial tuples `t` are stripped of
    zeros, their coefficient is the same as that of the monomial tuples from
    ``multinomial_coefficients(n, n)``. Therefore, the latter coefficients are
    precomputed to save memory and time.

    >>> from sympy.ntheory.multinomial import multinomial_coefficients
    >>> m53, m33 = multinomial_coefficients(5,3), multinomial_coefficients(3,3)
    >>> m53[(0,0,0,1,2)] == m53[(0,0,1,0,2)] == m53[(1,0,2,0,0)] == m33[(0,1,2)]
    True

    Examples
    ========

    >>> from sympy.ntheory.multinomial import multinomial_coefficients_iterator
    >>> it = multinomial_coefficients_iterator(20,3)
    >>> next(it)
    ((3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 1)
    r   r   Nr   )r+   r   filter)r   r   r   Zmcr   r*   Zmc1r   Zt1br'   r(   r   r   r   r%      s<    


r%   N)Z
__future__r   r   collectionsr   Zsympy.core.compatibilityr   r   r   r&   zipr#   r+   r%   r   r   r   r   <module>   s   :D