module Utils ( minMax, arrayFromList, invertArray, foldInteger, unfoldInteger ) where import Data.Array import Data.Tuple -- find min and max of list with one list traversal minMax :: (Ord a) => [a] -> (a, a) minMax (x:xs) = foldl (\(min, max) x -> (if x < min then x else min, if x > max then x else max)) (x, x) xs -- convert list to zero-based array arrayFromList :: [a] -> Array Integer a arrayFromList x = listArray (0, fromIntegral (length x) - 1) x -- if an array contains unique elements of Ix typeclass -- this function switches index and contents invertArray :: (Ix a, Ix b) => Array a b -> Array b a invertArray x = array (minMax $ map (snd) list) $ map (swap) list where list = assocs x -- take a function that splits an Integer in two values, stop if the integer is 0, -- make a list of the result of (Integer -> a) as used on the second value and -- pass the first value to itself foldIntegerHelper :: (Integer -> (Integer, Integer)) -> (Integer -> a) -> Integer -> [a] foldIntegerHelper calc trans x = recurse x [] where recurse 0 = id recurse x = recurse q . (:) (trans r) where (q, r) = calc x foldInteger :: Integer -> (Integer -> a) -> Integer -> [a] foldInteger div trans x = foldIntegerHelper (`quotRem` div) (trans) x -- make an integer from a list, by combining the current value of the Integer -- with the trans of current list element unfoldIntegerHelper :: (Integer -> Integer -> Integer) -> (a -> Integer) -> [a] -> Integer unfoldIntegerHelper calc trans = foldl (calc) 0 . (map (trans)) unfoldInteger :: Integer -> (a -> Integer) -> [a] -> Integer unfoldInteger mul trans = unfoldIntegerHelper ((+) . (mul*)) (trans)