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

1 Answer

0 votes
use std::fmt::Write;

/* ---------------------------------------------------------
   Compress: turn "aaabbcccc" into "a3b2c4"
   This is run-length encoding (RLE)
   --------------------------------------------------------- */
fn compress(s: &str) -> String {
    if s.is_empty() {
        return String::new();   // Edge case: empty string
    }

    let mut out = String::with_capacity(s.len()); // Result string
    let mut count: usize = 1;                     // Count of repeated characters
    let bytes = s.as_bytes();

    // Start from index 1 and compare with previous character
    for i in 1..=bytes.len() {

        // If still repeating the same character, increase count
        if i < bytes.len() && bytes[i] == bytes[i - 1] {
            count += 1;
        } else {
            // Character changed OR reached end of string
            out.push(bytes[i - 1] as char);   // Add the character
            write!(out, "{}", count).unwrap(); // Add how many times it repeated
            count = 1;                         // Reset counter
        }
    }

    out
}

/* ---------------------------------------------------------
   Decompress: turn "a3b2c4" into "aaabbcccc"
   Reads a letter, then reads digits, expands them.
   --------------------------------------------------------- */
fn decompress(s: &str) -> String {
    let mut out = String::new();      // Result string
    let mut current_char: Option<char> = None; // The character being processed
    let mut number = String::new();   // Digits representing the count

    for c in s.chars() {

        if c.is_alphabetic() {        // Found a letter
            // If we already have a previous letter + number, expand it
            if let Some(ch) = current_char {
                if !number.is_empty() {
                    let count: usize = number.parse().unwrap();
                    out.push_str(&ch.to_string().repeat(count));
                }
            }

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

        } else if c.is_numeric() {    // Found a digit
            number.push(c);           // Build multi-digit number
        }
    }

    // Handle the last character + number pair
    if let Some(ch) = current_char {
        if !number.is_empty() {
            let count: usize = number.parse().unwrap();
            out.push_str(&ch.to_string().repeat(count));
        }
    }

    out
}

fn main() {
    let s = "wwwwwwwwwwwwbwwwwwwwwwwbbbwwwwwwccccwwwwwwwwwwww";

    let c = compress(s);
    let d = decompress(&c);

    println!("Original:    {}", s);
    println!("Compressed:  {}", c);
    println!("Decompressed: {}", d);
}


/*
run:

Original:    wwwwwwwwwwwwbwwwwwwwwwwbbbwwwwwwccccwwwwwwwwwwww
Compressed:  w12b1w10b3w6c4w12
Decompressed: wwwwwwwwwwwwbwwwwwwwwwwbbbwwwwwwccccwwwwwwwwwwww

*/

 



answered 1 day ago by avibootz

Related questions

...