Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const fs=require("fs");
- var errorMessage = "An error occurred while reading the file";
- try{
- var str = fs.readFileSync(process.argv[3], "utf-8");
- }
- catch(ex){
- console.log(errorMessage);
- return;
- }
- if(str !== undefined && process.argv[4] !== undefined && process.argv[5] !== undefined && process.argv.length === 6)
- {
- if(process.argv[2] === "encode")
- {
- if(str === "")
- {
- console.log("nothing to compress");
- return;
- }
- var result = encode(str);
- try
- {
- fs.writeFileSync(process.argv[5], result.text, "utf-8");
- fs.writeFileSync(process.argv[4], result.table, "utf-8");
- }
- catch(ex)
- {
- console.log("An error occurred while writing the file");
- return;
- }
- echoTheoreticalCompression(str);
- console.log(((str.length * 8) / result.text.length).toFixed(2));
- }
- else if(process.argv[2] === "decode")
- {
- try
- {
- var decodeTable = fs.readFileSync(process.argv[4], "utf-8");
- }
- catch(ex)
- {
- console.log(errorMessage);
- return;
- }
- var decodeTable = decodeTableToArray(decodeTable);
- var result = decode(str, decodeTable);
- try
- {
- fs.writeFileSync(process.argv[5], result, "utf-8");
- }
- catch(ex)
- {
- console.log("An error occurred while writing the file");
- return;
- }
- }
- else
- console.log("error: incorrect input");
- }
- function echoTheoreticalCompression(str)
- {
- var entropy = getEntropy(getStat(str));
- if(entropy === 0)
- entropy = 1;
- console.log((8 / entropy).toFixed(2));
- }
- function encode(str)
- {
- var treeAndFirstIndex = createTree(str);
- var characterCodes = [];
- createCharacterCodeTable(treeAndFirstIndex.tree, treeAndFirstIndex.firstIndex, "", characterCodes);
- var encodedText = "";
- for(var i = 0; i < str.length; i++)
- {
- encodedText += characterCodes[str.charAt(i)];
- }
- var table = arrayToStringWithIndexes(characterCodes);
- return {
- table: table,
- text: encodedText
- };
- }
- function createTree(str)
- {
- var branches = [];
- for(var i = 0; i < str.length; i++)
- {
- if(branches[str.charAt(i)] !== undefined)
- {
- branches[str.charAt(i)].weight++;
- }
- else
- {
- branches[str.charAt(i)] = {
- weight: 1,
- left: null,
- right: null
- };
- }
- }
- var higherBranches = Object.assign({}, branches);
- var lastIndex = Object.keys(branches)[0];
- while(Object.keys(higherBranches).length > 1)
- {
- var firstLetter = findLetterWithMinWeight(higherBranches);
- var firstLetterWeight = higherBranches[firstLetter].weight;
- delete higherBranches[firstLetter];
- var secondLetter = findLetterWithMinWeight(higherBranches);
- var secondLetterWeight = higherBranches[secondLetter].weight;
- delete higherBranches[secondLetter];
- var newLetter = {
- weight: firstLetterWeight + secondLetterWeight,
- left: firstLetter,
- right: secondLetter
- };
- branches[firstLetter + secondLetter] = newLetter;
- higherBranches[firstLetter + secondLetter] = newLetter;
- if(Object.keys(higherBranches).length === 1)
- lastIndex = firstLetter + secondLetter;
- }
- return {
- tree: branches,
- firstIndex: lastIndex
- };
- }
- function findLetterWithMinWeight(higherBranches)
- {
- var letterWithMinWeight = Object.keys(higherBranches)[0];
- var minWeight = higherBranches[letterWithMinWeight].weight;
- for(var letter in higherBranches)
- {
- if(higherBranches[letter].weight < minWeight)
- {
- minWeight = higherBranches[letter].weight;
- letterWithMinWeight = letter;
- }
- }
- return letterWithMinWeight;
- }
- function createCharacterCodeTable(tree, firstIndex, currentPath, characterCodes)
- {
- if(Object.keys(tree).length === 1)
- {
- characterCodes[firstIndex] = 0;
- return;
- }
- if(tree[firstIndex].left === null)
- {
- characterCodes[firstIndex] = currentPath;
- return;
- }
- else
- {
- createCharacterCodeTable(tree, tree[firstIndex].left, currentPath + "0", characterCodes);
- createCharacterCodeTable(tree, tree[firstIndex].right, currentPath + "1", characterCodes);
- }
- }
- function arrayToStringWithIndexes(arr)
- {
- var result = "";
- for(var index in arr)
- {
- result += index + ":" + arr[index] + " ";
- }
- return result;
- }
- function decode(str, decodeTable)
- {
- var result = "";
- for(var i = 0; i < str.length; i++)
- {
- var index = str.charAt(i);
- if(!(index in decodeTable))
- {
- while(!(index in decodeTable) && i < str.length)
- {
- i++;
- index = index + str.charAt(i);
- }
- }
- if(decodeTable[index] === undefined)
- {
- console.log("error: impossible to decode text with this table");
- return result;
- }
- result += decodeTable[index];
- }
- return result;
- }
- function decodeTableToArray(decodeTable)
- {
- var result = [];
- var index = 0;
- while(index < decodeTable.length)
- {
- var i = index + 2;
- var value = "";
- while(decodeTable.charAt(i) !== " " && i < decodeTable.length)
- {
- value += decodeTable.charAt(i);
- i++;
- }
- result[value] = decodeTable.charAt(index);
- index = i + 1;
- }
- return result;
- }
- function getStat(str)
- {
- var stat = new Array();
- for(var i = 0; i < str.length; i++)
- {
- if(stat[str.charAt(i)] > 0)
- stat[str.charAt(i)]++;
- else
- stat[str.charAt(i)] = 1;
- }
- return stat;
- }
- function getEntropy(stat)
- {
- var lengthOfString = 0;
- for(var i in stat)
- {
- lengthOfString += stat[i];
- }
- var entropy = 0;
- for(var i in stat)
- {
- var p = stat[i] / lengthOfString;
- entropy += p * Math.log(p);
- }
- entropy *= (-1) / Math.log(2);
- return entropy;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement