String compression

Implemente uma função para executar a compactação de uma string simples usando um contador para os caracteres repetidos.

Por exemplo, a string aabcccccaaa deve retornar a2b1c5a3.

A compactação deve sempre retornar uma string com tamanho menor do que ao valor da entrada. Se não for, sua função deve retornar a string original.

Você pode assumir que a string tem apenas letras maísculas e minúsculas (az-AZ)

Dicas

Solução 1:

Eu comecei resolvendo o exercício pensando em iterar sob a string e comparar com o anterior.

Inicialmente, eu pensei em guardar a soma em uma Hash Table. No final, a lógica de comparar com o anterior ficou mais complexa, se comparada com as demaos soluções.

Segue solução:

      
function stringCompression (input) {
  const inputSize = input.length
  const tempObj = {}

  let result = ""
  let previous = ""

  for (let index = 0; index < inputSize; index++) {
    const currentCharacter = input[index];
    
    if (!tempObj[currentCharacter]) {
      tempObj[currentCharacter] = 1
    } else {
      tempObj[currentCharacter]++
    }

    if (previous && previous !== currentCharacter) {
      result = `${result}${previous}${tempObj[previous]}` 
      tempObj[previous] = 0
    } 

    previous = currentCharacter

    if (index === (inputSize - 1)) {
      result = `${result}${currentCharacter}${tempObj[currentCharacter]}` 

      if (result.length > inputSize) {
        result = input
      }
    }
  }

  return result
}
      
      

Solução 2:

Já a solução comparando o atual caracter com o próximo é bem mais simples.

Toda vez que o próximo caracter é diferente, fazemos a concatenação e resetamos o contador:

      
function stringCompression (input) {
  const inputLength = input.length
  let result = ""
  let count = 0

  for (let index = 0; index < inputLength; index++) {
    const currentCharacter = input[index];
    count++
    
    if (input[index + 1] !== currentCharacter) {
      result = `${result}${currentCharacter}${count}` 
      count = 0
    }
  }

  return result.length > inputLength
          ? input
          : result
              
}
      
      

Solução 3:

Como a concatenação de strings pode ficar "cara" computacionalmente falando, então pode ser melhor adicionar o resultado em um array push() e, no final, transformá-lo em string join():

      
function stringCompression (input) {
  const resultArray = []

  let count = 0

  for (let index = 0; index < input.length; index++) {
    const currentCharacter = input[index];
    count++
    
    if (input[index + 1] !== currentCharacter) {
    resultArray.push(currentCharacter)
    resultArray.push(count)
    count = 0
    }
  }

  const resultStr = resultArray.join("")

  return resultStr.length > input.length
          ? input
          : resultStr
}