56 lines
1.7 KiB
Rust
56 lines
1.7 KiB
Rust
fn encode(s: &str) -> String {
|
|
s.chars()
|
|
// wrap all values in Option::Some
|
|
.map(Some)
|
|
// add an Option::None onto the iterator to clean the pipeline at the end
|
|
.chain(std::iter::once(None))
|
|
.scan((0usize, '\0'), |(n, c), elem| match elem {
|
|
Some(elem) if *n == 0 || *c == elem => {
|
|
// the run continues or starts here
|
|
*n += 1;
|
|
*c = elem;
|
|
// this will not have an effect on the final string because it is empty
|
|
Some(String::new())
|
|
}
|
|
Some(elem) => {
|
|
// the run ends here
|
|
let run = format!("{}{}", n, c);
|
|
*n = 1;
|
|
*c = elem;
|
|
Some(run)
|
|
}
|
|
None => {
|
|
// the string ends here
|
|
Some(format!("{}{}", n, c))
|
|
}
|
|
})
|
|
// concatenate together all subresults
|
|
.collect()
|
|
}
|
|
|
|
fn decode(s: &str) -> String {
|
|
s.chars()
|
|
.fold((0usize, String::new()), |(n, text), c| {
|
|
if c.is_ascii_digit() {
|
|
// some simple number parsing
|
|
(
|
|
n * 10 + c.to_digit(10).expect("invalid encoding") as usize,
|
|
text,
|
|
)
|
|
} else {
|
|
// this must be the character that is repeated
|
|
(0, text + &format!("{}", c.to_string().repeat(n)))
|
|
}
|
|
})
|
|
.1
|
|
}
|
|
|
|
fn main() {
|
|
let text = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
|
|
let encoded = encode(text);
|
|
let decoded = decode(&encoded);
|
|
|
|
println!("original: {}\n encoded: {}\n decoded: {}", text, encoded, decoded);
|
|
assert_eq!(text, decoded);
|
|
}
|