'How to improve these haskell compress and decompress functions?
Specify the function that compresses a list by converting identical consecutive elements into number-by-element pairs. The group function can be useful.
Specify the function that restores the original from a compressed list. The replicate function can be useful.
import Data.List
compress :: (Eq a, Integral b) => [a] -> [(b, a)]
compress l = zip (length $ group l) (head $ group l)
Or:
compress :: (Eq a, Integral b) => [a] -> [(b, a)]
compress [] = []
compress (x:xs)
| x == a = (b+1,a) : xs
| otherwise = (1,a) : compress (b,a) xs
decompress :: (Eq a, Integral b) => [(b, a)] -> [a]
decompress l = concat [replicate (fst x) (snd x) | x <- l]
Examples:
compress "aaaabccaadeeee" == [(4, 'a'), (1, 'b'), (2, 'c'), (2, 'a'), (1, 'd'), (4, 'e')]
compress "oh hello !!" == [(1, 'o'), (1, 'h'), (1, ''), (1, 'h'), (1, 'e'), (2, 'l'), (1, 'o'), (2, '!')]
compress [] == []
compress [1,1,0,0,0,1,1,1] == [(2.1), (3.0), (3.1)]
decompress [(4, 'a'), (1, 'b'), (2, 'c'), (2, 'a'), (1, 'd'), (4, 'e')] == "aaaabccaadeeee"
decompress [(1, 'o'), (1, 'h'), (1, ''), (1, 'h'), (1, 'e'), (2, 'l'), ( 1, 'o'), (2, '!')] == "oh hello !!"
decompress [] == []
decompress [(2,1), (3,0), (3,1)] == [1,1,0,0,0,1,1,1]
Solution 1:[1]
You are here enumerating over the result of a group twice. You can simplify this and work with a mapping function that transforms each item of the result of group to a 2-tuple, for example with (&&&) :: Arrow a => a b c -> a b c' -> a b (c, c'). length :: Foldable f => f a -> Int returns an Int, so you can not use any Integral type:
import Control.Arrow((&&&))
compress :: Eq a => [a] -> [(Int, a)]
compress = map (length &&& head) . group
For decompressing, we can make use of concatMap :: Foldable t => (a -> [b]) -> t a -> [b] and use uncurry :: (a -> b -> c) -> (a, b) -> c to create a variant of replicate that works on a 2-tuple instead. replicate :: Int -> a -> [a] works on an Int, not any Integral, and the Eq type constraint is not necessary here, since we can replicate any item. concatMap can work on any Foldable, so we can generalize the type signature to:
decompress :: Foldable f => f (Int, a) -> [a]
decompress = concatMap (uncurry replicate)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Willem Van Onsem |
