Partitions of Integers


{-
 
  Program ...... : partition.hs (Partitions of Integers)
                   Partitions of Integers using generating function
  Author ....... : David Tran
  Date ......... : 2008-10-25
  References ... : http://en.wikipedia.org/wiki/Partition_%28number_theory%29
                   http://chowkafat.net/Enumeration15.html 

  ========================================================================
  
  Here shows example for n == 3
  * To simply the calculation, the coefficient of term x^0 is always ([],0)
  * most time we are interested only on term "n" (limited constant). 
    So any term > n is no need to calculate;
    that's the "max" for; so we will not have an infinity of terms Polynomial.

  term 3 1 = [ ([],0), ([(1,1)],1), ([(1,2)],2), ([(1,3)], 3) ]
           = ( 1 x^0 + (N1 x)^1 + (N1 x)^2 + (N1 x)^3 )
  term 3 2 = [ ([],0), ([(2,1)],2) ]
           = ( 1 x^0 + (N2 x)^1 )
  term 3 3 = [ ([],0), ([(3,1)],3) ]
           = ( 1 x^0 + (N3 x)^1 )

  multiple the 3 terms = (term 3 1* (term 3 2* (term 3 3)
  mult 3 (term 3 3$ mult 3 (term 3 1) (term 3 2)
  = [ ([],0), ([(2,1)],2), ([(1,1)],1), ([(1,1),(2,1)],3),
      ([(1,2)],2), ([(1,3)],3), ([(3,1)],3) ]

  ([(1,1),1) is for term x^1 => (1,1)           => 1 = 1
  for term x^2, we got [(2,1)] and [(1,2)]      => 2 = 2 = 1+1
  for term x^3, [(1,1),(2,1)], [(1,3)], [(3,1)] => 3 = 1 + 2
                                                     = 1 + 1 + 1
                                                     = 3
  
  ========================================================================

  Example Usage:

  *Main> partition 5
  [[(5,1)],[(2,1),(3,1)],[(1,1),(4,1)],[(1,1),(2,2)],[(1,2),(3,1)],[(1,3),(2,1)],[(1,5)]]

  *Main> pp_partition 5
  5=5
  5=2+3
  5=1+4
  5=1+2+2
  5=1+1+3
  5=1+1+1+2
  5=1+1+1+1+1

  *Main> countPartition 5
  7

-}

type Constant = (Int, Int)       -- "Constant" at "Position"
type Coefficient = [ Constant ]  -- "Sum" of Constant
type Exponent = Int
type Term = (Coefficient, Exponent)
type Polynomial = [ Term ]       -- "Sum" of Term

term :: Int -> Int -> Polynomial
term max n = ([],0: [ ([(n,i)], n * i) | i <- [1.. max `div` n ] ]

mult :: Int -> Polynomial -> Polynomial -> Polynomial
mult max p1 p2 = [ (c1++c2, e1+e2) | (c1,e1) <- p1, (c2,e2) <- p2, e1+e2 <= max ]

partition :: Int -> [ Coefficient ]
partition n = only_coeff $ filter_terms $ generate_terms
  where generate_terms = foldr1 (mult n) (map (term n) [1..n])
        filter_terms   = filter (\(c, e) -> e == n)
        only_coeff     = map (\(c, e) -> c)

countPartition :: Int -> Int
countPartition = length . partition

pp_partition :: Int -> IO()   -- pretty print partition
pp_partition n = sequence_ $ map showSum (partition n)
  where showSum s = do putStr $ (show n) ++ "=" ++ sumList (strList s) ++ "\n"
        strList = foldl (\acc (n,i) -> acc ++ replicate i (show n)) []
        sumList = foldl1 (\x y -> x ++ "+" ++ y)
        


Leave a Reply