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
*/