Skip to content

Instantly share code, notes, and snippets.

@adicuco
Created November 8, 2019 18:46
Show Gist options
  • Save adicuco/d18a166fd21fd5b183423a90e3d77a72 to your computer and use it in GitHub Desktop.
Save adicuco/d18a166fd21fd5b183423a90e3d77a72 to your computer and use it in GitHub Desktop.
JavaScript Huffman Encoding algorithm
const getFrequency = text => {
let freqs = [];
for (let i = 0; i < text.length; i++) {
const letter = text[i];
const letterIndex = freqs.findIndex(l => l.symbol === letter);
if (letterIndex > -1) {
freqs[letterIndex].weight++;
} else {
freqs.push({
symbol: letter,
weight: 1,
});
}
}
return freqs.sort((a, b) => a.weight - b.weight);
};
const buildTree = letters => {
let tree = letters;
while (tree.length > 1) {
const [s1, s2, ...rest] = tree;
const newWeight = s1.weight + s2.weight;
tree = rest;
tree.push({
symbol: s1.symbol + s2.symbol,
weight: newWeight,
0: s1,
1: s2,
});
tree.sort((a, b) => a.weight - b.weight);
}
return tree[0];
};
const buildSymbolCodes = (node, side = '', code = '') => {
const { symbol } = node;
const newCode = code + side;
if (symbol.length === 1) {
return [{ symbol, code: newCode }];
}
return [
...buildSymbolCodes(node[0], 0, newCode),
...buildSymbolCodes(node[1], 1, newCode),
];
};
const encode = (string, codes) => {
codes.forEach(symbol => {
string = string.replace(new RegExp(symbol.symbol, 'g'), symbol.code);
});
return string;
};
const decode = (string, tree) => {
let original = '';
let node = tree;
for (let i = 0; i < string.length; i++) {
const digit = string[i];
let letter = '';
const leaf = node[digit];
if (leaf.symbol.length === 1) {
letter += leaf.symbol;
node = tree;
} else {
node = leaf;
}
original += letter;
}
return original;
};
const [input] = process.argv.slice(2);
const inputs = [
'ABRACADABRA',
'MISSISSIPPI RIVER',
'A_DEAD_DAD_CEDED_A_BAD_BABE_A_BEADED_ABACA_BED',
];
const random = inputs[Math.floor(Math.random() * inputs.length)];
const start = string => {
console.log('original: ', string);
const freq = getFrequency(string);
const tree = buildTree(freq);
const codes = buildSymbolCodes(tree);
const code = encode(string, codes);
console.log('encoded: ', code);
console.log('decoded: ', decode(code, tree));
};
start(input || random);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment