Huffman Encoding
From HaskellWiki
(Difference between revisions)
m (Fixing spelling errors...) |
m (Reverted edits by LonnieGaudette (Talk); changed back to last version by Kashyap) |
||
| Line 85: | Line 85: | ||
displayAllEncodings :: [WeightCharacterTuple] -> Tree WeightCharacterTuple -> String | displayAllEncodings :: [WeightCharacterTuple] -> Tree WeightCharacterTuple -> String | ||
displayAllEncodings (x:xs) tree= (codeForX x) ++ "\n" ++ (displayAllEncodings xs tree) | displayAllEncodings (x:xs) tree= (codeForX x) ++ "\n" ++ (displayAllEncodings xs tree) | ||
| - | where codeForX (WeightCharacterTuple w c) = (show c) ++ " | + | where codeForX (WeightCharacterTuple w c) = (show c) ++ " weight = " ++ (show w) ++ " code = " ++ (encode x tree) |
displayAllEncodings _ _ = [] | displayAllEncodings _ _ = [] | ||
Current revision
data WeightCharacterTuple = WeightCharacterTuple {
weight :: Int,
character :: Char
}deriving (Show)
instance Eq WeightCharacterTuple where
a == b = (weight a) == (weight b)
instance Ord WeightCharacterTuple where
a > b = (weight a) > (weight b)
a >= b = (weight a) >= (weight b)
a < b = (weight a) < (weight b)
a <= b = (weight a) <= (weight b)
data Tree a = Node a (Tree a) (Tree a) | Leaf a
deriving (Show)
instance Eq a => Eq (Tree a) where
(==) a b = (node a) == (node b)
node x = case x of
(Node n _ _) -> n
(Leaf n) -> n
instance Ord a => Ord (Tree a) where
left >= right = (node left) >= (node right)
left < right = (node left) < (node right)
left > right = (node left) > (node right)
left <= right = (node left) <= (node right)
toFrequencyCharacterTuple :: String -> [WeightCharacterTuple]
toFrequencyCharacterTuple string = quickSort $ zipWith WeightCharacterTuple counts uniqueLetters
where
counts = map (frequency string) uniqueLetters
frequency :: String -> Char -> Int
frequency (x:xs) c
| c == x = 1 + frequency xs c
| otherwise = frequency xs c
frequency _ c = 0
uniqueLetters = unique string
unique :: String -> String -- get the unique letters in the string
unique (x:xs) = [x] ++ unique [y | y <- xs, y /= x ]
unique [] = []
huffman :: [Tree WeightCharacterTuple] -> [Tree WeightCharacterTuple]
huffman (min1:min2:rest) = huffman newList
where
newList
| length rest /= 0 = quickSort ((merge min1 min2):rest)
| otherwise = [merge min1 min2]
where merge a b
| a <= b = Node (WeightCharacterTuple newWeight '*') a b
| otherwise = Node (WeightCharacterTuple newWeight '*') b a
where newWeight = (weight (node a)) + (weight (node b))
huffman x = x
x `endsWith` y = (take (length y) (reverse x)) == (reverse y)
encode::WeightCharacterTuple -> Tree WeightCharacterTuple -> String
encode w (Node n left right) = oneOf ('0':(encode w left)) ('1':(encode w right))
where oneOf x y
| y `endsWith` "WRONG-LEAF" = x
| otherwise = y
encode w (Leaf l)
| (character l) == (character w) = ""
| otherwise = "WRONG-LEAF"
quickSort (x:xs) = l1 ++ [x] ++ l2 -- items less than x + x + items bigger than x
where
l1 = quickSort [y | y <- xs, y < x] -- sorted items less than x
l2 = quickSort [y | y <- xs, y >= x] -- sorted items greater than x
quickSort [] = []
displayAllEncodings :: [WeightCharacterTuple] -> Tree WeightCharacterTuple -> String
displayAllEncodings (x:xs) tree= (codeForX x) ++ "\n" ++ (displayAllEncodings xs tree)
where codeForX (WeightCharacterTuple w c) = (show c) ++ " weight = " ++ (show w) ++ " code = " ++ (encode x tree)
displayAllEncodings _ _ = []
main=do
x <- getLine
let tupleList=toFrequencyCharacterTuple x
let inputTreeList=map Leaf tupleList
let tree=huffman inputTreeList
putStrLn (show tree)
putStrLn (displayAllEncodings tupleList (tree!!0))
return ()
weight :: Int,
character :: Char
}deriving (Show)
instance Eq WeightCharacterTuple where
a == b = (weight a) == (weight b)
instance Ord WeightCharacterTuple where
a > b = (weight a) > (weight b)
a >= b = (weight a) >= (weight b)
a < b = (weight a) < (weight b)
a <= b = (weight a) <= (weight b)
data Tree a = Node a (Tree a) (Tree a) | Leaf a
deriving (Show)
instance Eq a => Eq (Tree a) where
(==) a b = (node a) == (node b)
node x = case x of
(Node n _ _) -> n
(Leaf n) -> n
instance Ord a => Ord (Tree a) where
left >= right = (node left) >= (node right)
left < right = (node left) < (node right)
left > right = (node left) > (node right)
left <= right = (node left) <= (node right)
toFrequencyCharacterTuple :: String -> [WeightCharacterTuple]
toFrequencyCharacterTuple string = quickSort $ zipWith WeightCharacterTuple counts uniqueLetters
where
counts = map (frequency string) uniqueLetters
frequency :: String -> Char -> Int
frequency (x:xs) c
| c == x = 1 + frequency xs c
| otherwise = frequency xs c
frequency _ c = 0
uniqueLetters = unique string
unique :: String -> String -- get the unique letters in the string
unique (x:xs) = [x] ++ unique [y | y <- xs, y /= x ]
unique [] = []
huffman :: [Tree WeightCharacterTuple] -> [Tree WeightCharacterTuple]
huffman (min1:min2:rest) = huffman newList
where
newList
| length rest /= 0 = quickSort ((merge min1 min2):rest)
| otherwise = [merge min1 min2]
where merge a b
| a <= b = Node (WeightCharacterTuple newWeight '*') a b
| otherwise = Node (WeightCharacterTuple newWeight '*') b a
where newWeight = (weight (node a)) + (weight (node b))
huffman x = x
x `endsWith` y = (take (length y) (reverse x)) == (reverse y)
encode::WeightCharacterTuple -> Tree WeightCharacterTuple -> String
encode w (Node n left right) = oneOf ('0':(encode w left)) ('1':(encode w right))
where oneOf x y
| y `endsWith` "WRONG-LEAF" = x
| otherwise = y
encode w (Leaf l)
| (character l) == (character w) = ""
| otherwise = "WRONG-LEAF"
quickSort (x:xs) = l1 ++ [x] ++ l2 -- items less than x + x + items bigger than x
where
l1 = quickSort [y | y <- xs, y < x] -- sorted items less than x
l2 = quickSort [y | y <- xs, y >= x] -- sorted items greater than x
quickSort [] = []
displayAllEncodings :: [WeightCharacterTuple] -> Tree WeightCharacterTuple -> String
displayAllEncodings (x:xs) tree= (codeForX x) ++ "\n" ++ (displayAllEncodings xs tree)
where codeForX (WeightCharacterTuple w c) = (show c) ++ " weight = " ++ (show w) ++ " code = " ++ (encode x tree)
displayAllEncodings _ _ = []
main=do
x <- getLine
let tupleList=toFrequencyCharacterTuple x
let inputTreeList=map Leaf tupleList
let tree=huffman inputTreeList
putStrLn (show tree)
putStrLn (displayAllEncodings tupleList (tree!!0))
return ()
