/
problem50.ml
66 lines (60 loc) · 2.56 KB
/
problem50.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
(*# P50 (***) Huffman code.
#
# First of all, consult a good book on discrete mathematics or algorithms for a
# detailed description of Huffman codes!
#
# We suppose a set of symbols with their frequencies, given as a list of fr(S,F) terms.
# Example: [fr(a,45),fr(b,13),fr(c,12),fr(d,16),fr(e,9),fr(f,5)].
#
# Our objective is to construct a list hc(S,C) terms, where C is the Huffman code
# word for the symbol S. In our example, the result could be Hs = [hc(a,'0'),
# hc(b,'101'), hc(c,'100'), hc(d,'111'), hc(e,'1101'), hc(f,'1100')]
# [hc(a,'01'),...etc.]. The task shall be performed by the predicate huffman/2
# defined as follows:
#
# % huffman(Fs,Hs) :- Hs is the Huffman code table for the frequency table Fs
#
# Binary Trees
#
# A binary tree is either empty or it is composed of a root element and two
# successors, which are binary trees themselves. In Lisp we represent the empty
# tree by 'nil' and the non-empty tree by the list (X L R), where X denotes the
# root node and L and R denote the left and right subtree, respectively. The
# example tree depicted opposite is therefore represented by the following list:
#
# (a (b (d nil nil) (e nil nil)) (c nil (f (g nil nil) nil)))
#
# Other examples are a binary tree that consists of a root node only:
#
# (a nil nil) or an empty binary tree: nil.
#
# You can check your predicates using these example trees. They are given as test
# cases in p54.lisp.*)
(* l is list of pairs [frequency,element] *)
let huffmann l =
(* make list of freqs and lists of elem code pairs *)
let l = List.map ( fun (f,e) -> (f,[(e,"")]) ) l in
(* fun to sort by freq, ascending *)
let sortbyfreq =
List.sort ( fun (f,m) (g,n) -> if f>g then 1 else 0 )
in
(* fun to append character x to code c of each pair in list of elem code pairs *)
let appendtocode x = List.map ( fun (e,c) -> (e,x^c) ) in
let rec combine_rare l =
(* sort by freq, a 1-step bubblesort would be better here *)
let l = sortbyfreq l in
match l with
(* take two least frequent elements from list *)
(f,m)::(g,n)::t ->
combine_rare ((f+g,(appendtocode "0" m)@(appendtocode "1" n))::t)
(* if list contains less than two elements *)
| _ -> l
in
(* return list of elem and code pairs *)
match ( List.hd ( combine_rare l ) ) with ( f, m ) -> m
;;
let print_codes l =
List.iter ( fun (e,c) -> Printf.printf "%s=%s " e c ) l;
Printf.printf "\n"
;;
print_codes ( huffmann [(45,"a");(13,"b");(12,"c");(16,"d");(9,"e");(5,"f")] );;