Skip to content

Commit 2cac750

Browse files
committed
Add Huffman Encoding in Racket
1 parent 4a74c1e commit 2cac750

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#lang racket
2+
3+
(require data/heap)
4+
5+
(struct branch (freq left right))
6+
(struct leaf (sym freq))
7+
8+
(define (weight node)
9+
(if (branch? node)
10+
(branch-freq node)
11+
(leaf-freq node)))
12+
13+
(define (make-huffman-tree leaves)
14+
(define (combine x y)
15+
(branch (+ (weight x) (weight y)) x y))
16+
17+
(define hp (make-heap
18+
(lambda (x y)
19+
(<= (weight x) (weight y)))))
20+
21+
(heap-add-all! hp leaves)
22+
23+
(define (merge)
24+
(if (= (heap-count hp) 1)
25+
; if there's only one node in the heap then return that element
26+
(heap-min hp)
27+
28+
; else merge the two smallest nodes
29+
(let ((a (heap-min hp)))
30+
; get the smallest node and remove it
31+
(heap-remove-min! hp)
32+
33+
(let ((b (heap-min hp)))
34+
; get the second smallest node and remove it
35+
(heap-remove-min! hp)
36+
37+
; add the combined node to the heap
38+
(heap-add! hp (combine a b))
39+
(merge)))))
40+
(merge))
41+
42+
(define (make-codebook tree)
43+
(define ht (make-hash))
44+
45+
(define (dfs node path)
46+
(if (leaf? node)
47+
; if node is a leaf then add the symbol to the codebook
48+
(hash-set! ht (leaf-sym node) path)
49+
(begin (dfs (branch-left node) (append path (list 0)))
50+
(dfs (branch-right node) (append path (list 1))))))
51+
52+
(dfs tree null)
53+
ht)
54+
55+
(define (encode codebook msg)
56+
(if (null? msg)
57+
null
58+
(append (hash-ref codebook (car msg))
59+
(encode codebook (cdr msg)))))
60+
61+
(define (decode tree msg)
62+
(define (dfs node bits)
63+
(if (leaf? node)
64+
(cons (leaf-sym node) (decode tree bits))
65+
(if (= (car bits) 0)
66+
(dfs (branch-left node) (cdr bits))
67+
(dfs (branch-right node) (cdr bits)))))
68+
69+
(if (null? msg)
70+
null
71+
(dfs tree msg)))
72+
73+
(define (generate-leaves msg)
74+
(define ht (make-hash))
75+
(for ([ch msg])
76+
(hash-update! ht ch add1 (lambda () 0)))
77+
(for/list ([(k v) (in-hash ht)])
78+
(leaf k v)))
79+
80+
; test
81+
(define message (string->list "bibbity bobbity"))
82+
(define leaves (generate-leaves message))
83+
(define huffman-tree (make-huffman-tree leaves))
84+
(define codebook (make-codebook huffman-tree))
85+
86+
(define encoded (encode codebook message))
87+
(define decoded (list->string (decode huffman-tree encoded)))
88+
89+
(println encoded)
90+
(println decoded)

‎contents/huffman_encoding/huffman_encoding.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ Whether you use a stack or straight-up recursion also depends on the language, b
9393
[import, lang:"asm-x64"](code/asm-x64/huffman.s)
9494
{% sample lang="scala" %}
9595
[import, lang:"scala"](code/scala/huffman_encoding.scala)
96+
{% sample lang="racket" %}
97+
[import, lang:"lisp"](code/racket/huffman.rkt)
9698
{% sample lang="scratch" %}
9799
The code snippet was taken from this [scratch project](https://scratch.mit.edu/projects/389604255/)
98100
<p>

0 commit comments

Comments
(0)