Presentation is loading. Please wait.

Presentation is loading. Please wait.

Functional Programming Lecture 16 - Case Study: Huffman Codes con’t.

Similar presentations


Presentation on theme: "Functional Programming Lecture 16 - Case Study: Huffman Codes con’t."— Presentation transcript:

1 Functional Programming Lecture 16 - Case Study: Huffman Codes con’t

2 Frequencies to Code Tree How do we build a code tree with optimal codes? 1. Find frequencies of individual characters. i) scan message and pair each character with a count of 1 e.g. [(‘b’,1),(‘a’, 1),(‘t’,1), (‘t’,1 ),(‘a’,1),(‘t’,1)] from “battat” ii) bring together counts, and sort e.g. [(‘a’,2),‘(‘b’,1),(‘t’,3)] iii) and sort on frequency e.g. [(‘b’,1),(‘a’,2),(‘t’,3)]

3 2. Build up tree by repeatedly taking 2 characters which occur least frequently and make a single character, or tree. i) build a leaf node from each character and sort e.g. [Leaf ‘b’1, Leaf ‘a’, 2, Leaf ‘t’ 3] ii) amalgamate together, pairwise, according to smallest frequencies, until a single tree is built e.g. [Leaf ‘b’ 1, Leaf ‘a’ 2, Leaf ‘t’ 3] then [Node 3 (Leaf ‘b’1),(Leaf ‘a’, 2), Leaf ‘t’ 3] then [Node 6 (Node 3 (Leaf ‘b’1) (Leaf ‘a’, 2)) (Leaf ‘t’ 3)]

4 Tree to table t b a This tree can be turned into a table: b [ L,L] a [L,R] t [R] In Haskell a list of pairs: [(‘b’,[L,L]), (‘a’, [L,R]), (‘t’, [R])]

5 Frequencies Finding frequencies involves - count each character, - add together counts, - sort list This means we sort twice - to bring together the counts, - to sort on frequency So, we will define a mergeSort and reuse: frequency :: [Char] -> [(Char,Int)] -- count each character, add together counts, -- -- then sort list -- frequency = (mergeSort freqMerge). (mergeSort alphaMerge). (map start) where start ch = (ch,1)

6 mergeSort :: ([a] -> [a] -> [a]) -> [a] -> [a] -- merge, in order, the results of sorting the front -- -- and rear halves of the list -- mergeSort merge xs | length xs < 2 = xs | otherwise = merge (mergeSort merge first) (mergeSort merge second) where first = take half xs second = drop half xs half = (length xs ) ‘div’ 2

7 Now, the two different “merge”’s -- compare characters, amalgamate entries for same -- -- character -- alphamerge:: [(Char,Int)] -> [(Char,Int)] -> [(Char,Int)] alphaMerge xs [] = xs alphaMerge [] ys = ys alphaMerge ((p,n):xs) ((q,m):ys) | (p==q) = (p,n+m) : alphaMerge xs ys | (p<q) = (p,n) : alphaMerge xs ((q,m):ys) | otherwise = (q,m) : alphaMerge ((p,n):xs) ys

8 -- compare frequencies, sort on frequency -- freqmerge :: [(Char,Int)] -> [(Char,Int)] -> [(Char,Int)] freqMerge xs [] = xs freqMerge [] ys = ys freqMerge ((p,n):xs) ((q,m):ys) | (n<m || (n==m && p<q)) = (p,n) : freqMerge xs ((q,m):ys) | otherwise = (q,m) : freqMerge ((p,n):xs) ys

9 Make Code Tree Make code tree from list of frequencies. Two stages: turn each char-frequency into a tree, successively pair trees until one tree. makeTree :: [(Char,Int)] -> Tree makeTree = makeCodes. toTreeList -- turn each char-frequency into a tree -- toTreeList :: [(Char,Int)] -> [Tree] toTreeList = map (uncurry Leaf) How does this work? By treating a constructor as a function! data Tree = Leaf Char Int | Node … can be viewed as defining a function Leaf :: Char->Int -> Tree E.g. data Bool = True | False defines two functions True :: Bool, False :: Bool.

10 -- successively pair trees -- makeCodes :: [Tree] -> Tree makeCodes [t] = t makeCodes ts = makeCodes (amalgamate ts) -- amalgamate trees -- -- pair together first two in list -- -- insert result in list in ascending order -- amalgamate :: [Tree] -> [Tree] amalgamate (t1:t2:ts) = insTree (pair t1 t2) ts -- pair trees, combining frequency counts -- pair :: Tree -> Tree -> Tree pair t1 t2 = Node (v1+v2) t1 t2 where v1 = value t1 v2 = value t2 value :: Tree -> Int value (Leaf _ n) = n value (Node n _ _ ) = n -- insert a tree into a list -- -- sorted by frequency -- insTree :: Tree -> [Tree] -> [Tree ]

11 Code Table Finally, convert a Huffman tree into a table of codes. codeTable :: Tree -> Table codeTable = convert [] -- build up table of character, code pairs -- -- the code describes the path “so far” -- -- to a character -- convert :: Hcode -> Tree -> Table convert code (Leaf ch f) = [(ch,code)] convert code (Node f t1 t2) = (convert (code ++ [L]) t1) ++ (convert (code ++ [R]) t2)

12 E.g. codeTable (Node 6 (Node 3 (Leaf ‘b’1) (Leaf ‘a’, 2)) (Leaf ‘t’ 3)) = convert [] (Node 6 (Node 3 (Leaf ‘b’1) (Leaf ‘a’, 2)) (Leaf ‘t’ 3)) = (convert [L] (Node 3 (Leaf ‘b’1) (Leaf ‘a’, 2)) ) ++ (convert [R] ( Leaf ‘t’, 3 )) = (convert [L,L] (Leaf ‘b’1) ) ++ (convert [L,R] (Leaf ‘a’2) ) ++ (convert [R] ( Leaf ‘t’, 3 )) = [(‘b’,[L,L])] ++ [(‘a’,[L,R])] ++ [(‘t’,[R])] = [(‘b’,[L,L]), (‘a’,[L,R]), (‘t’,[R])] This hasn’t been easy! Read Book - Section 15.3 onwards (to end of Chapter)

13 Note: Haskell provides mechanisms for dealing with programming in the large, i.e. modularity, but these are not covered in this course.

14


Download ppt "Functional Programming Lecture 16 - Case Study: Huffman Codes con’t."

Similar presentations


Ads by Google