Compress Repeated Characters with Run-Length Encoding
Encode repeated characters with counts and decode the result back, rejecting zero counts and dangling numeric prefixes.
Code
fn encode(input: &str) -> String {
let mut output = String::new();
let mut characters = input.chars().peekable();
while let Some(current) = characters.next() {
let mut count = 1usize;
while characters.peek() == Some(¤t) {
characters.next();
count += 1;
}
if count > 1 {
output.push_str(&count.to_string());
}
output.push(current);
}
output
}
fn decode(input: &str) -> Result<String, String> {
let mut output = String::new();
let mut digits = String::new();
for character in input.chars() {
if character.is_ascii_digit() {
digits.push(character);
continue;
}
let count = if digits.is_empty() {
1
} else {
digits
.parse::<usize>()
.map_err(|_| format!("invalid count: {digits}"))?
};
if count == 0 {
return Err("count must be positive".to_string());
}
output.extend(std::iter::repeat(character).take(count));
digits.clear();
}
if !digits.is_empty() {
return Err("trailing count without a character".to_string());
}
Ok(output)
}
fn main() {
for sample in ["aaabccdddd", "abc", "wwwwwwwwwwww"] {
let encoded = encode(sample);
let decoded = decode(&encoded).expect("valid encoding");
println!("{sample} -> {encoded} -> {decoded}");
assert_eq!(decoded, sample);
}
assert_eq!(encode("aaabccdddd"), "3ab2c4d");
assert!(decode("0a").is_err());
assert!(decode("12").is_err());
}
Report a problem with this exampleOpens a pre-filled issue on GitHub.