-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhuffman_coding.sf
66 lines (54 loc) · 1.33 KB
/
huffman_coding.sf
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
#!/usr/bin/ruby
# https://rosettacode.org/wiki/huffman_coding
func walk(Hash n, String s, Hash h) {
if (n.has(:a)) {
h{n{:a}} = s
printf("%3s: %s\n", n{:a}, s)
return nil
}
walk(n{:0}, s+'0', h) if n.has(:0)
walk(n{:1}, s+'1', h) if n.has(:1)
}
func make_tree(Array bytes) {
var nodes = bytes.freq.sort.map_2d { |b,f|
Hash(a => b, freq => f)
}
loop {
nodes.sort_by!{|h| h{:freq} }
var(x, y) = (nodes.shift, nodes.shift)
if (defined(x)) {
if (defined(y)) {
nodes << Hash(:0 => x, :1 => y, :freq => x{:freq}+y{:freq})
}
else {
nodes << Hash(:0 => x, :freq => x{:freq})
}
}
nodes.len > 1 || break
}
var n = nodes.first
walk(n, '', n{:tree} = Hash())
return n
}
func encode(bytes, t) {
t = t{:tree}
bytes.map { t{_} }.join
}
func decode(enc, tree) {
var out = []
var prefix = ''
enc.each {|bit|
prefix += bit
if (tree.has(prefix)) {
out << tree{prefix}
prefix = ''
}
}
return out
}
var text = "this is an example for huffman encoding"
var bytes = text.bytes
var tree = make_tree(bytes)
var enc = encode(bytes, tree)
say enc
say decode(enc, tree{:tree}.flip).decode('utf8')