1+ from email .quoprimime import decodestring
2+ from locale import windows_locale
3+
4+
5+ class Node :
6+ def __init__ (self , char , weight , left = None , right = None ):
7+ self .char = char
8+ self .weight = weight
9+ self .left = left
10+ self .right = right
11+
12+ def __lt__ (self , other ):
13+ return other .weight > self .weight
14+
15+ def getCode (self , char , parentPath ):
16+ if self .char == char :
17+ return parentPath
18+
19+ if self .left :
20+ left_path = self .left .getCode (char , parentPath + "0" )
21+ if left_path :
22+ return left_path
23+
24+ if self .right :
25+ right_path = self .right .getCode (char , parentPath + "1" )
26+ if right_path :
27+ return right_path
28+
29+
30+ return None
31+
32+
33+
34+ def countTable (msg : str ) -> dict [str , int ]:
35+ dict_table = {}
36+ for char in msg :
37+ if char in dict_table :
38+ dict_table [char ] += 1
39+ else :
40+ dict_table [char ] = 1
41+
42+ return dict_table
43+
44+ def huffman (nodes : list [Node ]) -> Node :
45+ while len (nodes ) > 1 :
46+ nodes .sort ()
47+
48+ left = nodes .pop (0 )
49+ right = nodes .pop (0 )
50+
51+ parent = Node (None , left .weight + right .weight , left , right )
52+
53+ nodes .append (parent )
54+
55+ return nodes [0 ]
56+
57+ def encode (msg : str ) -> tuple [str , dict [str , str ]]:
58+ count_table = countTable (msg )
59+
60+ nodes = []
61+
62+ for char , weight in count_table .items ():
63+ nodes .append (Node (char , weight ))
64+
65+ no = huffman (nodes )
66+
67+ code_table = {}
68+ for i in count_table .keys ():
69+ code_table [i ] = no .getCode (i , "" )
70+
71+ encoded_msg = ""
72+
73+ for i in msg :
74+ encoded_msg += code_table [i ]
75+
76+ return encoded_msg , code_table
77+
78+ def decode (encoded : str , table : dict [str , str ]) -> str :
79+ left = 0
80+ values = table .values ()
81+
82+ decoded_msg = ""
83+
84+ for i in range (len (encoded )):
85+ cur = encoded [left :i + 1 ]
86+ for key , values in table .items ():
87+ if values == cur :
88+ decoded_msg += key
89+ left = i + 1
90+ break
91+
92+ return decoded_msg
93+
94+
95+ def encode_file (filepath ):
96+ with open (filepath , "r" ) as f_read :
97+ content = f_read .read ()
98+ encoded_str , table = encode (content )
99+ with open ("encoded.huff" , "w" ) as f_write :
100+ f_write .write (f'{ len (table )} \n ' )
101+ for key , values in table .items ():
102+ f_write .write (key + ":" + values + "\n " )
103+ f_write .write (encoded_str )
104+
105+
106+ def decode_file (filepath ):
107+ with open (filepath , "r" ) as f_read :
108+ ln = f_read .readline ()
109+ table = {}
110+ for _ in range (int (ln )):
111+ line = f_read .readline ()
112+ key , value = line .split (":" )
113+ table [key ] = value [0 :len (value ) - 1 ]
114+ content = f_read .read ()
115+ decoded_str = decode (content , table )
116+ with open ("decoded.txt" , "w" ) as f :
117+ f .write (decoded_str )
118+
119+ str , table = encode ("Hello fsdfdfsdfsdfsdfsdfsdfsdfdsfsdfdsfWorld" )
120+
121+ decodestring = decode (str , table )
122+
123+ print (decodestring )
124+
125+
126+ encode_file ("file.txt" )
127+
128+ decode_file ("encoded.huff" )
0 commit comments