Last active
September 28, 2023 15:20
-
-
Save Aldizh/a1d18e934ad9f2d3f9445371ef321b14 to your computer and use it in GitHub Desktop.
Compress/Decompress a string input using a reversible formula
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Write a compression and decompression algorithm that results in a smalller string | |
// You can assume all the input parameters are letters of the alphabet | |
function isNumber(char) { | |
return !Number.isNaN(parseInt(char)) && typeof parseInt(char) === 'number' | |
} | |
// str is in this format, number then letter => "2a4f7s154v..." | |
function decompress(str) { | |
if (!str) return str | |
let decompressed = "" | |
for (let i = 0; i < str.length; i++) { | |
let count = parseInt(str.charAt(i), 10) | |
if (isNumber(count)) { | |
// parse the number and advance the index | |
let nextChar = str.charAt(i + 1) | |
// loop through for cases where count is > 9, e.g: 134s | |
let numberSequence = str.charAt(i) | |
while (isNumber(nextChar)) { | |
numberSequence += str.charAt(i + 1) | |
nextChar = str.charAt(i + 1) | |
i = i + 1 | |
} | |
// add count characters to the final string | |
count = parseInt(numberSequence, 10) | |
for (var j = 0; j < count; j++) { | |
if (nextChar) decompressed += nextChar | |
} | |
} | |
} | |
return decompressed | |
} | |
// This algorithm looks at the next letter to look for a change | |
// Its a sliding window approach where we keep count of the same letter groupings and increment/reset the count accordingly | |
function compress(str) { | |
if (!str) return str | |
let sameLetterGrouping = "" | |
let compressed = "" | |
for (let i = 0; i < str.length; i++) { | |
const letter = str.charAt(i) | |
const differentNextLetter = letter !== str.charAt(i + 1) | |
// multiple occurences | |
if (sameLetterGrouping.includes(letter)) { | |
// increment occurrence count | |
const count = parseInt(sameLetterGrouping.substring(0, sameLetterGrouping.length - 1), 10) | |
sameLetterGrouping = `${count + 1}${sameLetterGrouping.substring(sameLetterGrouping.length - 1)}` | |
if (differentNextLetter) compressed += sameLetterGrouping | |
} else { | |
sameLetterGrouping = `1${letter}` | |
if (!compressed.includes(letter) && differentNextLetter) compressed += sameLetterGrouping | |
} | |
} | |
return compressed | |
} | |
// "aaassdduuiasigdj" | |
function compress_looking_backwards(str){ | |
let finalStr = ''; | |
let count = 1; | |
for (var i = 1; i < str.length; i++) { | |
const currentLetter = str[i] | |
const previousLetter = str[i-1] | |
if (currentLetter === previousLetter) { | |
count += 1; | |
} else { | |
// we hit another letter | |
finalStr += `${count}${previousLetter}` | |
count = 1; | |
} | |
} | |
// add the last letter with its corresponding count | |
finalStr += `${count}${str[str.length - 1]}` | |
return finalStr; | |
} | |
// testing: decompressed should always match original string | |
const tests = [ | |
"saaabbbbcdddd", | |
"ssaaabbsssbbccdddd", | |
"sssaaabbsssbbccdddd", | |
"ssssssssssssssssssttaaaaaaaaaaaaaaaa" | |
] | |
for (test of tests) { | |
// const compressed = compress(test) | |
const compressed = compress_looking_backwards(test) | |
const decompressed = decompress(compressed) | |
console.log(test === decompressed) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment