forked from shellfly/algo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlzw.go
65 lines (61 loc) · 1.19 KB
/
lzw.go
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
package algs4
// LZW ...
type LZW struct {
R int // number of input chars
L int // number of codewords = 2^W
W int // codeword width
}
// NewLZW ...
func NewLZW() *LZW {
return &LZW{256, 4096, 12}
}
// Compress ...
func (l *LZW) Compress() {
input := BinaryStdin.ReadString()
st := NewTST()
for i := 0; i < l.R; i++ {
st.Put(string(i), i)
}
code := l.R + 1 // R is codeword for EOF
for len(input) > 0 {
s := st.LongPrefixOf(input) // Find max prefix match s.
BinaryStdout.WriteBits(st.Get(s).(int), l.W) // Print s's encoding.
t := len(s)
if t < len(input) && code < l.L {
st.Put(input[0:t+1], code)
code++
}
input = input[t:]
}
BinaryStdout.WriteBits(l.R, l.W)
BinaryStdout.Close()
}
// Expand ...
func (l *LZW) Expand() {
st := make([]string, l.L)
var i int
for i = 0; i < l.R; i++ {
st[i] = string(i)
}
st[i] = " "
i++
codeword := BinaryStdin.ReadIntR(l.W)
val := st[codeword]
for {
BinaryStdout.WriteStr(val)
codeword = BinaryStdin.ReadIntR(l.W)
if codeword == l.R {
break
}
s := st[codeword]
if i == codeword {
s = val + string(val[0])
}
if i < l.L {
st[i] = val + string(s[0])
i++
}
val = s
}
BinaryStdout.Close()
}