Skip to content

Instantly share code, notes, and snippets.

@Aldizh
Last active September 28, 2023 15:20
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 Aldizh/a1d18e934ad9f2d3f9445371ef321b14 to your computer and use it in GitHub Desktop.
Save Aldizh/a1d18e934ad9f2d3f9445371ef321b14 to your computer and use it in GitHub Desktop.
Compress/Decompress a string input using a reversible formula
// 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