huffman-ts
Version:
Huffman ts is an implementation of Huffman Algorithm in Typescript. It provides full compatibility with Huffman algorithm reference.
246 lines (193 loc) • 5.62 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
/**
* Huffman tree node type:
* 1. [not Leaf node] have left, right child, do not have value
* 2. [Leaf node] do not have left and right, have value
*/
var TreeNode = /*#__PURE__*/function () {
function TreeNode() {
this.left = null;
this.right = null;
this.value = null;
}
var _proto = TreeNode.prototype;
_proto.isLeaf = function isLeaf() {
return this.left === null && this.right === null;
};
_proto.encode = function encode() {
if (this.value) {
return this.value;
}
return [this.left.encode(), this.right.encode()];
};
return TreeNode;
}();
/**
* Pad a string, used to pad bits into a full byte
*/
function lpad(str, len) {
if (str === void 0) {
str = '';
}
if (len === void 0) {
len = 8;
}
return '0'.repeat(len - str.length) + str;
}
var Tree = /*#__PURE__*/function () {
function Tree(root) {
this.leafCache = {};
this.root = root || new TreeNode();
}
var _proto = Tree.prototype;
_proto.stringToBitString = function stringToBitString(encoded) {
if (!encoded) {
return '';
}
var pieces = encoded.split(''),
pad = parseInt(pieces.pop()),
bitString = '';
bitString = pieces.map(function (ch) {
return lpad(ch.charCodeAt(0).toString(2));
}).join('');
return bitString.substr(0, bitString.length - pad);
};
_proto.bitStringToString = function bitStringToString(bitString) {
var padByte = 8 - bitString.length % 8,
encoded = '';
bitString = bitString + '0'.repeat(padByte);
for (var i = 0; i < bitString.length; i += 8) {
encoded += String.fromCharCode(parseInt(bitString.substr(i, 8), 2));
}
encoded += padByte.toString();
return encoded;
};
_proto.encode = function encode(text) {
var bitString = this.encodeBitString(text);
return this.bitStringToString(bitString);
};
_proto.decode = function decode(encoded) {
var _this = this;
if (!encoded) {
return '';
}
var decoded = '',
bitString = this.stringToBitString(encoded),
node = this.root;
bitString.split('').forEach(function (direction) {
var d = direction === '0' ? 'left' : 'right';
node = node[d];
if (node.isLeaf()) {
decoded += node.value;
node = _this.root;
}
});
return decoded;
};
_proto.encodeBitString = function encodeBitString(text) {
var _this2 = this;
return text.split('').map(function (ch) {
return _this2.bitValue(ch);
}).join('');
};
_proto.bitValue = function bitValue(ch) {
if (!this.leafCache[ch]) {
/**
* only run at first time call which will generate all ch related code
*/
this.generateLeafCache();
}
return this.leafCache[ch];
};
_proto.generateLeafCache = function generateLeafCache(node, path) {
if (node === void 0) {
node = this.root;
}
if (path === void 0) {
path = '';
}
if (node.isLeaf()) {
this.leafCache[node.value] = path;
} else {
this.generateLeafCache(node.left, path + '0');
this.generateLeafCache(node.right, path + '1');
}
};
_proto.encodeTree = function encodeTree() {
return this.root.encode();
};
Tree.decodeTree = function decodeTree(data) {
return new Tree(Tree.parseNode(data));
};
Tree.parseNode = function parseNode(data) {
var node = new TreeNode();
if (Array.isArray(data)) {
node.left = Tree.parseNode(data[0]);
node.right = Tree.parseNode(data[1]);
} else {
node.value = data;
}
return node;
};
return Tree;
}();
var TreeBuilder = /*#__PURE__*/function () {
function TreeBuilder(text) {
this.rawString = text;
}
var _proto = TreeBuilder.prototype;
_proto.build = function build() {
var table = this.buildFrequencyTable();
var item = this.combineTable(table);
var compressedTable = this.compressCombinedTable(item);
return Tree.decodeTree(compressedTable);
};
_proto.frequencySorter = function frequencySorter(a, b) {
return a[1] - b[1];
};
_proto.combineTable = function combineTable(table) {
while (table.length > 1) {
var first = table.shift();
var second = table.shift();
table.unshift([[first, second], first[1] + second[1]]);
table.sort(this.frequencySorter);
}
return table[0];
};
_proto.buildFrequencyTable = function buildFrequencyTable() {
var tableHash = {};
this.rawString.split('').forEach(function (chr) {
tableHash[chr] = tableHash[chr] ? tableHash[chr] + 1 : 1;
});
return Object.entries(tableHash).sort(this.frequencySorter);
};
_proto.compressCombinedTable = function compressCombinedTable(item) {
var value = item[0];
if (Array.isArray(value)) {
return [this.compressCombinedTable(value[0]), this.compressCombinedTable(value[1])];
}
return value;
};
return TreeBuilder;
}();
/**
* Author: @wizardpisces
* Contact: 1275839779@qq.com
* Date: 2021-3-8
* typescript version of https://github1s.com/wilkerlucio/huffman_js
*/
var Huffman = /*#__PURE__*/function () {
function Huffman() {}
Huffman.treeFromText = function treeFromText(text) {
var builder = new TreeBuilder(text);
return builder.build();
};
Huffman.decodeTree = function decodeTree(data) {
return Tree.decodeTree(data);
};
return Huffman;
}();
exports.Huffman = Huffman;
exports.Tree = Tree;
//# sourceMappingURL=huffman-ts.cjs.development.js.map