-
Notifications
You must be signed in to change notification settings - Fork 2
/
algo.js
152 lines (120 loc) · 3.79 KB
/
algo.js
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/**
algo.js
CODING PRACTICE
Vincent Le Quang
April 18, 2015
*/
function Algo() {
this.start = function() {
}
this.compress = function(text) {
// DYNAMIC HUFFMAN
function getValue(obj) {
return -obj.frequency;
}
function getBinary(char) {
var code = char.charCodeAt(0);
var str = "";
for(var i=0;i<8;i++) {
str = ((code & (1<<i))?"1":"0") + str;
}
return str;
}
function getTableBinary(root,code) {
if(root.left && root.right) {
code.push("1");
getTableBinary(root.left,code);
getTableBinary(root.right,code);
}
else {
code.push("0");
code.push(getBinary(root.char));
}
}
var heap = [];
var nodes = {
};
for(var i=0;i<text.length;i++) {
var char = text.charAt(i);
var node = nodes[char];
if(!node) {
node = nodes[char] = {char:char,frequency:0};
}
node.frequency++;
}
for(var c in nodes) {
heapInsert(heap,nodes[c],getValue);
}
while(heap.length>1) {
var low1 = heapRetrieve(heap,getValue);
var low2 = heapRetrieve(heap,getValue);
heapInsert(heap,{left:low1,right:low2,frequency:low1.frequency+low2.frequency},getValue);
}
// create huffman map
var map = {};
function createMap(map,node,code) {
if(node.left && node.right) {
createMap(map,node.left,code+"0");
createMap(map,node.right,code+"1");
}
else {
map[node.char] = code;
}
}
createMap(map,heap[0],"");
console.log(map);
// compress
// store table first
var treeCode = [];
getTableBinary(heap[0],treeCode);
var codes = [];
for(var i=0;i<text.length;i++) {
var char = text.charAt(i);
codes.push(map[char]);
}
console.log(codes.join("").length);
return treeCode.join("")+codes.join("");
}
this.uncompress = function(text) {
// turn the text into an array and reverse for easy pop
var input = text.split("").reverse();
function getCharacter(input) {
var num = 0;
for(var i=0;i<8;i++) {
num <<=1;
num += input[input.length-1-i]=='1'?1:0;
}
input.splice(input.length-8);
return String.fromCharCode(num);
}
// first retrieve the table
function retrieveTable(input) {
var root = {};
var inp = input.pop();
if(inp=='1') {
root.left = retrieveTable(input);
root.right = retrieveTable(input);
}
else {
root.char = getCharacter(input);
}
return root;
}
var table = retrieveTable(input);
function decode(input,table,chars) {
if(!table.left && !table.right) {
chars.push(table.char);
return;
}
var inp = input.pop();
if(inp=='0')
decode(input,table.left,chars);
else
decode(input,table.right,chars);
}
var chars = [];
while(input.length)
decode(input,table,chars);
return chars.join("");
}
}