-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhuffman.py
executable file
·115 lines (102 loc) · 2.61 KB
/
huffman.py
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/env python3
import sys, argparse, heapq
freqs = {
' ': 18.23,
'A': 6.22,
'B': 1.32,
'C': 3.11,
'D': 2.97,
'E': 10.53,
'F': 1.68,
'G': 1.65,
'H': 3.63,
'I': 6.14,
'J': 0.07,
'K': 0.31,
'L': 3.07,
'M': 2.48,
'N': 5.73,
'O': 6.06,
'P': 1.87,
'Q': 0.1,
'R': 5.87,
'S': 5.81,
'T': 7.68,
'U': 2.27,
'V': 0.7,
'W': 1.13,
'X': 0.25,
'Y': 1.07,
'Z': 0.05
}
def count_freqs(text):
freqs = {}
for c in text:
freqs[c] = freqs.get(c, 0) + 1
return freqs
def build_tree(freqs):
heap = [(f, i, v) for i, (v, f) in enumerate(freqs.items())]
heapq.heapify(heap)
i = len(heap)
while len(heap) > 1:
freq1, _, node1 = heapq.heappop(heap)
freq2, _, node2 = heapq.heappop(heap)
heapq.heappush(heap, ((freq1 + freq2), i, (node1, node2)))
i += 1
return heap[0][2]
def make_table(tree, pre='', dct=None):
if dct is None: dct = {}
for i, node in enumerate(tree):
if not isinstance(node, tuple):
dct[node] = pre + str(i)
else:
make_table(node, pre + str(i), dct)
return dct
def huffman(freqs):
tree = build_tree(freqs)
return make_table(tree)
tree = build_tree(freqs)
entable = make_table(tree)
detable = {v: k for k, v in entable.items()}
def encode(text, table=entable):
return ''.join(table.get(c.upper(), '') for c in text)
def decode(msg, table=detable):
out, nxt = '', ''
for c in msg:
if c.isspace():
continue
nxt += c
if nxt in table:
out += table[nxt]
nxt = ''
return out
def decode2(msg, tree=tree):
out = ''
node = tree
for c in msg:
if c == '0':
node = node[0]
elif c == '1':
node = node[1]
else:
continue
if isinstance(node, str):
out += node
node = tree
return out
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-t', '--table', action='store_true')
parser.add_argument('-e', '--encode', action='store_true', default=True,
help='(default)')
parser.add_argument('-d', '--decode', action='store_true')
parser.add_argument('file', nargs='?', type=argparse.FileType(),
default=sys.stdin)
args = parser.parse_args()
if args.table:
for k, v in sorted(entable.items()):
print('{}: {}'.format(k, v))
elif args.decode:
print(decode(args.file.read()))
else:
print(encode(args.file.read()))