Skip to content

Instantly share code, notes, and snippets.

@sebinsua
Created November 8, 2020 20:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sebinsua/97a8bca51188903d3199c1dad5694c96 to your computer and use it in GitHub Desktop.
Save sebinsua/97a8bca51188903d3199c1dad5694c96 to your computer and use it in GitHub Desktop.
function letterFrequency(str) {
const uniques = {};
for (let char of str) {
uniques[char] = uniques[char] ? ++uniques[char] : 1;
}
return uniques;
}
function letterFrequencyTemplate(uniques) {
return Object.entries(uniques)
.map(([char, count]) => `${char}${count}`)
.join("");
}
function compress(str) {
let compressed = "";
let lastChar;
let count;
for (let char of str) {
if (char === lastChar) {
count++;
continue;
}
if (lastChar) {
compressed += lastChar;
if (count > 1) {
compressed += `${count}`;
}
}
lastChar = char;
count = 1;
}
if (lastChar) {
compressed += lastChar;
if (count > 1) {
compressed += `${count}`;
}
}
return compressed;
}
function compress2(str) {
let compressed = "";
function append(currentChar, count) {
compressed += currentChar;
if (count > 1) {
compressed += `${count}`;
}
}
let lastChar;
let count;
for (let char of str) {
if (char === lastChar) {
count++;
continue;
}
if (lastChar) append(lastChar, count);
lastChar = char;
count = 1;
}
if (lastChar) append(lastChar, count);
return compressed;
}
function compress3(str, separator = "") {
let compressed = "";
function append(currentChar, count) {
if (compressed.length) {
compressed += separator;
}
compressed += currentChar;
if (count > 1) {
compressed += `${count}`;
}
}
let lastChar;
let count;
for (let char of str) {
if (char === lastChar) {
count++;
continue;
}
if (lastChar) append(lastChar, count);
lastChar = char;
count = 1;
}
if (lastChar) append(lastChar, count);
return compressed;
}
function* reverse(str) {
for (let idx = str.length - 1; idx >= 0; idx--) {
yield str[idx];
}
}
function decompress(str) {
const NUMBER_REGEX = /\d/;
let decompressed = "";
function append(currentChar, _count) {
const count = Number(_count.length ? _count : 1);
let chunk = currentChar;
if (count > 1) {
chunk = new Array(count).fill(currentChar).join("");
}
decompressed = `${chunk}${decompressed}`;
}
let count = "";
for (let char of reverse(str)) {
if (NUMBER_REGEX.test(char)) {
count = `${char}${count}`;
continue;
}
append(char, count);
count = "";
}
return decompressed;
}
console.log(letterFrequencyTemplate(letterFrequency("aabbbcccccdd")));
console.log(compress("aabbbcccccdd"));
console.log(compress2("aabbbcccccdd"));
console.log(compress3("xyyzzz", ","));
console.assert(
compress3("aabbbcccccdd") === "a2b3c5d2",
"Could not compress correctly!"
);
// NOTE:
// Without a separator it is not possible to decompress strings with numbers in them
// because if you see something like 'a2b34', there could be 34 b characters at the
// end or 3 b characters followed by a 4 character.
// However, if there is a separator then these are distinct (e.g. 'a2,b34' and 'a2,b3,4').
console.log(decompress("a2b3c5d2"));
console.log(decompress("x7y2z14"));
console.assert(
decompress("a2b3c5d2") === "aabbbcccccdd",
"Failed to decompress!"
);
@sebinsua
Copy link
Author

sebinsua commented Nov 9, 2022

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment