combinat-0.2.4.1: Math/Combinat/Compositions.hs
-- | Compositions.
-- This module is equivalent to the module "Combinations",
-- but it turns out that \"compositions\" is the accepted name. I will
-- remove the "Combinations" module in the future.
module Math.Combinat.Compositions where
import Math.Combinat.Numbers (factorial,binomial)
-------------------------------------------------------
-- | Compositions fitting into a given shape and having a given degree.
-- The order is lexicographic, that is,
--
-- > sort cs == cs where cs = compositions' shape k
--
compositions'
:: [Int] -- ^ shape
-> Int -- ^ sum
-> [[Int]]
compositions' [] 0 = [[]]
compositions' [] _ = []
compositions' shape@(s:ss) n =
[ x:xs | x <- [0..min s n] , xs <- compositions' ss (n-x) ]
countCompositions' :: [Int] -> Int -> Integer
countCompositions' [] 0 = 1
countCompositions' [] _ = 0
countCompositions' shape@(s:ss) n = sum
[ countCompositions' ss (n-x) | x <- [0..min s n] ]
-- | All compositions fitting into a given shape.
allCompositions' :: [Int] -> [[[Int]]]
allCompositions' shape = map (compositions' shape) [0..d] where d = sum shape
-- | Compositions of a given length.
compositions
:: Integral a
=> a -- ^ length
-> a -- ^ sum
-> [[Int]]
compositions len' d' = compositions' (replicate len d) d where
len = fromIntegral len'
d = fromIntegral d'
-- | # = \\binom { len+d-1 } { len-1 }
countCompositions :: Integral a => a -> a -> Integer
countCompositions len d = binomial (len+d-1) (len-1)
-- | Positive compositions of a given length.
compositions1
:: Integral a
=> a -- ^ length
-> a -- ^ sum
-> [[Int]]
compositions1 len' d'
| len > d = []
| otherwise = map plus1 $ compositions len (d-len)
where
plus1 = map (+1)
len = fromIntegral len'
d = fromIntegral d'
countCompositions1 :: Integral a => a -> a -> Integer
countCompositions1 len d = countCompositions len (d-len)
-------------------------------------------------------