How to compress and decompress repeated string characters by storing the repeated length (RLE) in Scala

1 Answer

0 votes
import scala.collection.mutable.StringBuilder

/* ---------------------------------------------------------
   Compress: turn "aaabbcccc" into "a3b2c4"
   This is run-length encoding (RLE)
   --------------------------------------------------------- */
def compress(s: String): String = {
  if (s.isEmpty)
    return ""   // Edge case: empty string

  val out = new StringBuilder()   // Result string
  var count = 1                   // Count of repeated characters

  // Start from index 1 and compare with previous character
  for (i <- 1 to s.length) {

    // If still repeating the same character, increase count
    if (i < s.length && s(i) == s(i - 1)) {
      count += 1
    } else {
      // Character changed OR reached end of string
      out.append(s(i - 1))        // Add the character
      out.append(count.toString)  // Add how many times it repeated
      count = 1                   // Reset counter
    }
  }

  out.toString()
}


/* ---------------------------------------------------------
   Decompress: turn "a3b2c4" into "aaabbcccc"
   Reads a letter, then reads digits, expands them.
   --------------------------------------------------------- */
def decompress(s: String): String = {
  val out = new StringBuilder()   // Result string
  var currentChar: Option[Char] = None   // The character being processed
  val number = new StringBuilder()       // Digits representing the count

  for (c <- s) {

    if (c.isLetter) {             // Found a letter
      // If we already have a previous letter + number, expand it
      currentChar.foreach { ch =>
        if (number.nonEmpty) {
          val count = number.toString.toInt
          out.append(ch.toString * count)
        }
      }

      currentChar = Some(c)       // Start new character
      number.clear()              // Reset number buffer

    } else if (c.isDigit) {       // Found a digit
      number.append(c)            // Build multi-digit number
    }
  }

  // Handle the last character + number pair
  currentChar.foreach { ch =>
    if (number.nonEmpty) {
      val count = number.toString.toInt
      out.append(ch.toString * count)
    }
  }

  out.toString()
}


@main def main(): Unit = {
  val s = "wwwwwwwwwwwwbwwwwwwwwwwbbbwwwwwwccccwwwwwwwwwwww"

  val c = compress(s)
  val d = decompress(c)

  println(s"Original:    $s")
  println(s"Compressed:  $c")
  println(s"Decompressed: $d")
}



/*
run:

Original:    wwwwwwwwwwwwbwwwwwwwwwwbbbwwwwwwccccwwwwwwwwwwww
Compressed:  w12b1w10b3w6c4w12
Decompressed: wwwwwwwwwwwwbwwwwwwwwwwbbbwwwwwwccccwwwwwwwwwwww

*/

 



answered 1 day ago by avibootz

Related questions

...