module Combinatorics.Partitions (
pentagonalPowerSeries,
numPartitions,
partitionsInc,
partitionsDec,
allPartitionsInc,
propInfProdLinearFactors,
propPentagonalPowerSeries,
propPentagonalsDifP,
propPentagonalsDifN,
propPartitions,
propNumPartitions,
) where
import qualified Data.List as List
import qualified PowerSeries as PS
import Data.Eq.HT (equating)
prodLinearFactors :: Int -> PS.T Integer
prodLinearFactors n =
foldl PS.mul [1] $ take n $ map (1:) $ iterate (0:) [-1]
infProdLinearFactors :: PS.T Integer
infProdLinearFactors =
zipWith (!!)
(scanl (\prod i -> delayedSub prod i prod) [1] [1..])
[0..]
propInfProdLinearFactors :: Int -> Bool
propInfProdLinearFactors n =
and $
take (n+1) $
zipWith (==)
infProdLinearFactors
(prodLinearFactors n)
pentagonalsP, pentagonalsN,
pentagonalsDifP, pentagonalsDifN :: [Int]
pentagonalsP = map (\n -> div (n*(3*n-1)) 2) [0..]
pentagonalsN = map (\n -> div (n*(3*n+1)) 2) [0..]
pentagonalsDifP = map (\n -> 3*n+1) [0..]
pentagonalsDifN = map (\n -> 3*n+2) [0..]
propPentagonalsDifP :: Int -> Bool
propPentagonalsDifP n =
equating (take n)
pentagonalsDifP (zipWith (-) (tail pentagonalsP) pentagonalsP)
propPentagonalsDifN :: Int -> Bool
propPentagonalsDifN n =
equating (take n)
pentagonalsDifN (zipWith (-) (tail pentagonalsN) pentagonalsN)
delayedSub :: [Integer] -> Int -> [Integer] -> [Integer]
delayedSub x del y =
let (a,b) = splitAt del x
in a ++ PS.sub b y
numPartitions :: [Integer]
numPartitions =
let accu = foldr (delayedSub numPartitions) (error "never evaluated")
ps = accu (tail pentagonalsDifP)
ns = accu (tail pentagonalsDifN)
in 1 : zipWith (+) ps (0:ns)
pentagonalPowerSeries :: [Integer]
pentagonalPowerSeries =
let make = concat . zipWith (\s n -> s : replicate (n-1) 0) (cycle [1,-1])
in flip PS.sub [1] $
PS.add
(make pentagonalsDifP)
(make pentagonalsDifN)
propPentagonalPowerSeries :: Int -> Bool
propPentagonalPowerSeries n =
equating (take n) infProdLinearFactors pentagonalPowerSeries
partitionsInc :: (Integral a) => a -> a -> [[a]]
partitionsInc k n =
concatMap (\y -> map (y:) (partitionsInc y (n-y))) [k .. div n 2] ++ [[n]]
partitionsDec :: (Integral a) => a -> a -> [[a]]
partitionsDec 0 0 = [repeat 0]
partitionsDec _ 0 = []
partitionsDec k n =
(if k>=n then [[n]] else []) ++
concatMap (\y -> map (y:) (partitionsDec y (n-y)))
(takeWhile (>0) (iterate pred (min n k)))
_partitionsInc :: (Integral a) => a -> a -> [[a]]
_partitionsInc k n =
if k>n
then []
else concatMap (\y -> map (y:) (_partitionsInc y (n-y))) [k..(n-1)]
++ [[n]]
allPartitionsInc :: [[[[Int]]]]
allPartitionsInc =
let part :: Int -> Int -> [[Int]]
part k n = concatMap (\y -> map (y:) (xs !! y !! (n-y)))
[k .. div n 2]
++ [[n]]
xs = repeat [[]] : map (\k -> map (part k) [0..]) [1..]
in xs
propPartitions :: Int -> Int -> Bool
propPartitions k n =
partitionsInc k n == allPartitionsInc !! k !! n
propNumPartitions :: Int -> Bool
propNumPartitions n =
equating (take n)
(map List.genericLength (allPartitionsInc !! 1)) numPartitions