;ò
L‘Fc           @   sY   d  Z  d g d „ Z d f  d „  ƒ  YZ e ƒ  Z e d „ Z e d „ Z d d „ Z d S(	   sD   Combinatorics.

$Id: Pascal.py,v 1.1 2007/03/08 23:49:49 eddy Exp $
i   c         C   sñ   |  d j  o t d ‚ n y | |  SWn t j
 o n X| d t | ƒ f \ } } xŽ |  | j o€ y | | } Wn# t j
 o t | ƒ | } n Xd | } t | ƒ d j  o+ | i	 | ƒ | t | ƒ j p t
 ‚ q[ q[ W| Sd S(   s•  Returns the factorial of any natural number.

	Equivalent to reduce(lambda a,b:a*(1+b), range(num), 1L), except that it
	doesn't return a long unless it has to (or num is one) and it degrades
	gracefully when given invalid input.

        For agrguments < 0 this raises a ValueError.  For other arguments < 1,
	you'll get the answer 1, as this is correct if your argument is valid
	and resolves the problem of what to do with invalid input.  For other
	non-integer non-negative values, you'll get a computed positive value
	which probably isn't far off the Gamma function's value at one more than
	that non-integer.  For valid input, i.e. non-negative integers,
	factorial(num) = Gamma(1+num), wherein

	Gamma(1+a) = integral(: exp(-t).power(a, t) &larr;t :{positive reals})

	for arbitrary a in the complex plane, with a pole (of order 1) at each
	negative integer and a real humdinger of a singularity at infinity. i    s   I only do naturalsiÿÿÿÿi   i   N(   s   nums
   ValueErrors   caches
   IndexErrors   lens   results   is   OverflowErrors   longs   appends   AssertionError(   s   nums   caches   is   result(    (    s(   /home/eddy/.sys/py/study/maths/Pascal.pys	   factorial   s&           
#s   Pascalc           B   s>   t  Z d  Z h  Z d „  Z d „  Z d „  Z e Z d „  Z RS(   s]  A dictionary describing Pascal's triangle.

    Keys are pairs of naturals; value for (n,m) is (n+m)! / n! / m!

    Given the symmetry, no value is actually stored for key (n,m) when m > n.
    Given the nature of Pascal's triangle, computing the value for a given (n,m)
    involves computing the values for all (i,j) with i<=n and j<=m.

    Representation depicts Pascal's triangle with one side as the top line, the
    other as the left column; a `row' of Pascal's triangle is thus a diagonal
    stripe.  Only values we've actually needed are shown, so there's nothing
    above the diagonal; except on the top line, where a 1 is displayed above the
    last digit of the diagonal entry in each column.

    Note that neither this class nor its one instance is any part of this
    module's export: it is over-ridden by a curried form of chose(), below.
c         C   s¼   | \ } } y |  i | | ƒ } Wn t j
 oƒ } | GH| i d d j o ‚  n t	 | | ƒ t	 | ƒ t	 | ƒ } | | j  o | | f \ } } n | |  i
 | | f <n X| Sd  S(   Ni    s    maximum recursion depth exceeded(   s   keys   ns   ms   selfs   _Pascal__lookups   vals   RuntimeErrors   whats   argss	   factorials   _Pascal__values(   s   selfs   keys   whats   vals   ms   n(    (    s(   /home/eddy/.sys/py/study/maths/Pascal.pys   __getitem__=   s      $ c         C   s(  | | j  o | | f \ } } n | | j p t ‚ | d j  o d Sn | d j o d Sn | d j o | d Sn y |  i | | f } WnŒ t j
 o€ |  i | d | ƒ |  i | | d ƒ f \ } } y | | } Wn# t
 j
 o t | ƒ | } n X| |  i | | f <n X| Sd  S(   Ni    i   (   s   ns   ms   AssertionErrors   selfs   _Pascal__valuess   vals   KeyErrors   _Pascal__lookups   ups   lefts   OverflowErrors   long(   s   selfs   ns   ms   vals   ups   left(    (    s(   /home/eddy/.sys/py/study/maths/Pascal.pys   __lookupI   s&         2  c   
      C   s&  |  i i ƒ  } | o d Sn | i ƒ  g  }	 x’ | D]Š \ } } x6 | t |	 ƒ j o" |	 i d t |	 ƒ d g ƒ qE Wt |	 | d ƒ | j p t	 ‚ |	 | d i |  i | | f ƒ q6 Wt |	 ƒ d } xi | d j o[ | d } |	 | d } t | ƒ | d j  o | i d ƒ n d i | ƒ |	 | d <q× Wd } t | ƒ d t |	 ƒ d f \ } } } x˜ | | j  oŠ y t |	 | ƒ } Wn% t j
 o t |	 | | ƒ ‚ n X| | d } | d j  o Pn | d | d f | d | f \ } } } qqW| d	 d
 i |	 ƒ d Sd  S(   Ns   1, 1, ...
1,s   1i   i   s   ...s   , s   1, 1s   ,%*ds   , ...
s   ,
s   ,
...(   s   selfs   _Pascal__valuess   keyss   sorts   rows   ns   ms   lens   appends   AssertionErrors   heres   joins   heads   offs   news
   IndexErrors   gap(
   s   selfs   heads   offs   keyss   ms   ns   heres   news   gaps   row(    (    s(   /home/eddy/.sys/py/study/maths/Pascal.pys   __str__Y   sB     
  #"' 
 (   /c         C   s¢   g  } x} |  i i ƒ  D]l \ \ } } } t | | ƒ t | ƒ t | ƒ } | | j o) | i	 d | | f | d | ƒ q q W| o d i
 | ƒ Sn d S(   s/   Uses factorial() to verify results of chose(). s	   %d, %d ->s    != s   
N(   s   results   selfs   _Pascal__valuess   itemss   ns   ms   vals	   factorials   checks   appends
   joinfields(   s   selfs   vals   ms   ns   results   check(    (    s(   /home/eddy/.sys/py/study/maths/Pascal.pys   check~   s      $-(	   s   __name__s
   __module__s   __doc__s   _Pascal__valuess   __getitem__s   _Pascal__lookups   __str__s   __repr__s   check(    (    (    s(   /home/eddy/.sys/py/study/maths/Pascal.pys   Pascal*   s    			#c         C   s   | |  | | f Sd S(   s²   chose(N,i) -> N! / (N-i)! / i!

    This is the number of ways of chosing i items from among N, ignoring order
    of choice.  Computed using a cached form of Pascal's triangle. N(   s   racks   totals   part(   s   totals   parts   rack(    (    s(   /home/eddy/.sys/py/study/maths/Pascal.pys   chose‹   s     c         C   s   |  i ƒ  d  S(   N(   s   racks   check(   s   rack(    (    s(   /home/eddy/.sys/py/study/maths/Pascal.pys   check“   s    c         C   s*   t  t |  | d „ t d |  ƒ ƒ ƒ Sd S(   sf  A row of Pascal's triangle, optionally scaled, as a tuple.

    Required argument, tot, is the row index: Pascal(1+i)[1+j] = Pascal(i)[j] +
    Pascal(i)[1+j] give-or-take missing entries being presumed zero, with
    Pascal[0] = (1,).  Optional second argument is an over-all scaling to apply
    to all entries in the row; thus sum(Pascal(n, .5**n)) == 1.
c         C   s   t  | |  ƒ | S(   N(   s   choses   ts   is   s(   s   is   ts   s(    (    s(   /home/eddy/.sys/py/study/maths/Pascal.pys   <lambda>   s    i   N(   s   tuples   maps   tots   scales   range(   s   tots   scale(    (    s(   /home/eddy/.sys/py/study/maths/Pascal.pys   Pascal•   s     N(   s   __doc__s	   factorials   Pascals   choses   check(   s	   factorials   Pascals   choses   check(    (    s(   /home/eddy/.sys/py/study/maths/Pascal.pys   ?   s   $_	