combinat-compat-0.2.8.2: Math/Combinat/Partitions/Vector.hs
-- | Vector partitions. See:
--
-- * Donald E. Knuth: The Art of Computer Programming, vol 4, pre-fascicle 3B.
--
{-# LANGUAGE BangPatterns #-}
module Math.Combinat.Partitions.Vector where
--------------------------------------------------------------------------------
import Data.Array.Unboxed
import Data.List
--------------------------------------------------------------------------------
-- | Integer vectors. The indexing starts from 1.
type IntVector = UArray Int Int
-- | Vector partitions. Basically a synonym for 'fasc3B_algorithm_M'.
vectorPartitions :: IntVector -> [[IntVector]]
vectorPartitions = fasc3B_algorithm_M . elems
_vectorPartitions :: [Int] -> [[[Int]]]
_vectorPartitions = map (map elems) . fasc3B_algorithm_M
-- | Generates all vector partitions
-- (\"algorithm M\" in Knuth).
-- The order is decreasing lexicographic.
fasc3B_algorithm_M :: [Int] -> [[IntVector]]
{- note to self: Knuth's descriptions of algorithms are still totally unreadable -}
fasc3B_algorithm_M xs = worker [start] where
-- n = sum xs
m = length xs
start = [ (j,x,x) | (j,x) <- zip [1..] xs ]
worker stack@(last:_) =
case decrease stack' of
Nothing -> [visited]
Just stack'' -> visited : worker stack''
where
stack' = subtract_rec stack
visited = map to_vector stack'
decrease (last:rest) =
case span (\(_,_,v) -> v==0) (reverse last) of
( _ , [(_,_,1)] ) -> case rest of
[] -> Nothing
_ -> decrease rest
( second , (c,u,v):first ) -> Just (modified:rest) where
modified =
reverse first ++
(c,u,v-1) :
[ (c,u,u) | (c,u,_) <- reverse second ]
_ -> error "fasc3B_algorithm_M: should not happen"
to_vector cuvs =
accumArray (flip const) 0 (1,m)
[ (c,v) | (c,_,v) <- cuvs ]
subtract_rec all@(last:_) =
case subtract last of
[] -> all
new -> subtract_rec (new:all)
subtract [] = []
subtract full@((c,u,v):rest) =
if w >= v
then (c,w,v) : subtract rest
else subtract_b full
where w = u - v
subtract_b [] = []
subtract_b ((c,u,v):rest) =
if w /= 0
then (c,w,w) : subtract_b rest
else subtract_b rest
where w = u - v
--------------------------------------------------------------------------------