1+
2+ (* Takes in a string and a character that needs to be removed from
3+ the string that is input
4+ For eg. in a string : "Chennai" I want to remove char : 'n'
5+ such that we get the old value and the new value as a tuple
6+
7+ TL;DR : "Chennai" -> ("Cheai", "Chennai")
8+ *)
9+ let char_diff str ch =
10+ let res = String. concat " " (String. split_on_char ch str) in
11+ (res, str)
12+
13+ (* Converts "ABCD" -> ['A'; 'B'; 'C'; 'D'] *)
14+ let str_to_charlist s = List. init (String. length s) (String. get s)
15+
16+ (* Takes a word like "bibbity_bob" and converts to a tuple list of
17+ unique characters with their frequency
18+
19+ TL;DR :
20+ "bibbity_bobbity" ->
21+ [('b', 6); ('i', 3); ('t', 2); ('y', 2); ('_', 1); ('o', 1)]
22+ *)
23+ let counter str =
24+ let char_lst = str_to_charlist str in
25+ let rec loop acc str char_lst =
26+ match char_lst with
27+ | [] -> List. filter (fun (_ ,y ) -> y != 0 ) (List. rev acc)
28+ |> List. map (fun (x , y ) -> (Printf. sprintf " %c" x, y))
29+ | hd :: tl ->
30+ let (new_str, old_str) = char_diff str hd in
31+ loop
32+ ((hd, (String. length old_str - String. length new_str)) :: acc)
33+ new_str tl in
34+ loop [] str char_lst
35+
36+ (* References -> https://ocaml.org/learn/tutorials/99problems.html *)
37+
38+ module Pq = struct
39+ type 'a t = {
40+ data : 'a list array ;
41+ mutable first : int ;
42+ }
43+
44+ let make size = {
45+ data = Array. make size [] ;
46+ first = size;
47+ }
48+
49+ let add q p x =
50+ q.data.(p) < - x :: q.data.(p);
51+ q.first < - min p q.first
52+
53+ let get_min q =
54+ if q.first = Array. length (q.data) then None
55+ else
56+ match q.data.(q.first) with
57+ | [] -> assert false
58+ | hd :: tl ->
59+ let p = q.first in
60+ q.data.(q.first) < - tl;
61+ while q.first < (Array. length (q.data)) && q.data.(q.first) = [] do
62+ q.first < - q.first + 1
63+ done ;
64+ Some (p,hd)
65+ end
66+
67+ type tree = Leaf of string | Node of tree * tree
68+
69+ let rec create_huffman_tree q =
70+ match Pq. get_min q, Pq. get_min q with
71+ | Some (p1 , t1 ), Some (p2 , t2 ) ->
72+ Pq. add q (p1 + p2) (Node (t1, t2));
73+ create_huffman_tree q
74+ | Some (_ , t ), None | None , Some (_ , t ) -> t
75+ | None , None -> assert false
76+
77+ let rec prefixes_of_tree prefix trees = match trees with
78+ | Leaf s -> [(s, prefix)]
79+ | Node (t0 , t1 ) ->
80+ List. append (prefixes_of_tree (prefix ^ " 0" ) t0) (prefixes_of_tree (prefix ^ " 1" ) t1)
81+
82+ let huffman huffman_tree = prefixes_of_tree " " huffman_tree
83+
84+ (* Helper functions *)
85+ let char_to_str = Printf. sprintf " %c"
86+
87+ let str_list msg =
88+ List. map char_to_str (str_to_charlist msg)
89+
90+ let list_to_string lst =
91+ String. concat " " lst
92+
93+ (* Encoding and decoding functions *)
94+ let encode codebook x =
95+ List. filter (fun (ch , _ ) -> ch = x) codebook |> fun x ->
96+ List. hd x |> snd
97+
98+ let encode_msg codebook msg =
99+ List. map (fun x -> encode codebook x) (str_list msg) |>
100+ list_to_string (List. map (fun x -> encode codebook x) (str_list msg))
101+
102+ let decode codebook key =
103+ List. find_opt (fun (_ ,code ) -> key = code) codebook
104+
105+
106+ let decode_msg codebook msg =
107+ let decoded_message = ref " " in
108+ let code = ref " " in
109+ let msg_list = str_list msg in
110+ List. iter (fun bit ->
111+ code := ! code ^ bit;
112+ match (decode codebook ! code) with
113+ | None -> ()
114+ | Some v ->
115+ decoded_message := ! decoded_message ^ (fst v);
116+ code := " " ;
117+ ) msg_list;
118+ ! decoded_message
119+
120+ (* Printing functions below *)
121+ let print_codebook codebook =
122+ let _ = Printf. printf " [\n " in
123+ let fmt_tup hd = Printf. sprintf " \t (%s, %s)" (fst hd) (snd hd) in
124+ let rec loop codebook = match codebook with
125+ | [] -> ()
126+ | hd :: [] ->
127+ let tup = fmt_tup hd in
128+ Printf. printf " %s\n ]\n " tup
129+ | hd :: tl ->
130+ let tup = fmt_tup hd in
131+ Printf. printf " %s,\n " tup;
132+ loop tl in
133+ loop codebook
134+
135+ let rec print_huffman_tree huffman_tree =
136+ match huffman_tree with
137+ | Leaf a -> Printf. sprintf " %s" a
138+ | Node (l , r ) ->
139+ let fmt_l = print_huffman_tree l in
140+ let fmt_r = print_huffman_tree r in
141+ Printf. sprintf " [%s,%s]" fmt_l fmt_r
142+
143+
144+ (* Main Function *)
145+ let _ =
146+ let message = " bibbity_bobbity" in
147+ let freq_ch_list = counter message in
148+ let size = List. fold_left (fun sum (_ ,p ) -> sum + p) 0 freq_ch_list in
149+ let queue = Pq. make (size + 2 ) in
150+ let _ = List. iter (fun (s ,f ) -> Pq. add queue f (Leaf s)) freq_ch_list in
151+ let huffman_tree = create_huffman_tree queue in
152+ let codebook = huffman huffman_tree in
153+ let encoded_message = encode_msg codebook message in
154+ let decoded_message = decode_msg codebook encoded_message in
155+ let _ = Printf. printf " Message : %s\n " message in
156+ let _ = print_huffman_tree huffman_tree |> fun x ->
157+ Printf. printf " Huffman Tree : %s\n " x in
158+ let _ = Printf. printf " Codebook : " ;print_codebook codebook in
159+ let _ = Printf. printf " Encoded Message : %s\n " encoded_message in
160+ let _ = Printf. printf " Decoded Message : %s\n " decoded_message in
161+ ()
0 commit comments