-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlzw.py
64 lines (45 loc) · 1.41 KB
/
lzw.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
def lzw_compress(uncompressed: str) -> list[int]:
dict_size = 256
dictionary = {chr(i): i for i in range(dict_size)}
print(dictionary)
w = ""
result: list[int] = []
for c in uncompressed:
wc = w + c
if wc in dictionary:
w = wc
else:
result.append(dictionary[w])
dictionary[wc] = dict_size
dict_size += 1
w = c
if w:
result.append(dictionary[w])
return result
def lzw_decompress(compressed: list[int]) -> str:
dict_size = 256
dictionary = {i: chr(i) for i in range(dict_size)}
result: list[str] = []
w = chr(compressed.pop(0))
result.append(w)
for k in compressed:
if k in dictionary:
entry = dictionary[k]
elif k == dict_size:
entry = w + w[0]
else:
raise ValueError(f"Bad compressed k: {k}")
result.append(entry)
dictionary[dict_size] = w + entry[0]
dict_size += 1
w = entry
return "".join(result)
if __name__ == "__main__":
original = "TOBEORNOTTOBEORTOBEORNOT"
print(f"Original: {original}")
compressed = lzw_compress(original)
print(f"Compressed: {compressed}")
decompressed = lzw_decompress(compressed)
print(f"Decompressed: {decompressed}")
if original != decompressed:
raise ValueError("Decompressed data does not match original data")