// Decode Run-Length Encoding โ 99 Problems #12
// Expand RLE back to original list
#[derive(Debug, PartialEq, Clone)]
enum Rle<T> {
One(T),
Many(usize, T),
}
fn decode<T: Clone>(lst: &[Rle<T>]) -> Vec<T> {
lst.iter()
.flat_map(|item| match item {
Rle::One(x) => vec![x.clone()],
Rle::Many(n, x) => vec![x.clone(); *n],
})
.collect()
}
/// Tail-recursive style using an iterator accumulator.
fn decode_tr<T: Clone>(lst: &[Rle<T>]) -> Vec<T> {
let mut result = Vec::new();
for item in lst {
match item {
Rle::One(x) => result.push(x.clone()),
Rle::Many(n, x) => {
for _ in 0..*n {
result.push(x.clone());
}
}
}
}
result
}
fn main() {
let encoded = vec![
Rle::Many(4usize, 'a'),
Rle::One('b'),
Rle::Many(2, 'c'),
Rle::Many(2, 'a'),
Rle::One('d'),
Rle::Many(4, 'e'),
];
println!("Encoded: {:?}", encoded);
println!("Decoded: {:?}", decode(&encoded));
println!("Decoded (tr): {:?}", decode_tr(&encoded));
let singles = vec![Rle::One('x'), Rle::One('y')];
println!("Singles decoded: {:?}", decode(&singles));
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_decode_empty() {
let empty: Vec<Rle<char>> = vec![];
assert_eq!(decode(&empty), Vec::<char>::new());
}
#[test]
fn test_decode_singles() {
let encoded = vec![Rle::One('a'), Rle::One('b')];
assert_eq!(decode(&encoded), vec!['a', 'b']);
}
#[test]
fn test_decode_mixed() {
let encoded = vec![Rle::Many(3, 'a'), Rle::One('b'), Rle::Many(2, 'c')];
assert_eq!(decode(&encoded), vec!['a', 'a', 'a', 'b', 'c', 'c']);
}
#[test]
fn test_decode_tr_matches_decode() {
let encoded = vec![Rle::Many(2, 'x'), Rle::One('y')];
assert_eq!(decode(&encoded), decode_tr(&encoded));
}
}
(* Decode Run-Length Encoding โ 99 Problems #12 *)
type 'a rle =
| One of 'a
| Many of int * 'a
(* โโ Using List.concat_map (OCaml 4.10+) โโโโโโโโโโโโโโโโโโ *)
let decode lst =
List.concat_map (function
| One x -> [x]
| Many (n, x) -> List.init n (fun _ -> x))
lst
(* โโ Recursive with accumulator โโโโโโโโโโโโโโโโโโโโโโโโโโโโ *)
let decode_recursive lst =
let rec expand = function
| One x -> [x]
| Many (0, _) -> []
| Many (n, x) -> x :: expand (Many (n - 1, x))
in
let rec aux acc = function
| [] -> List.rev acc
| item :: rest -> aux (List.rev_append (expand item) acc) rest
in aux [] lst
(* โโ Tail-recursive version โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ *)
let decode_tr lst =
let rec aux acc = function
| [] -> List.rev acc
| One x :: rest -> aux (x :: acc) rest
| Many (0, _) :: rest -> aux acc rest
| Many (n, x) :: rest -> aux (x :: acc) (Many (n - 1, x) :: rest)
in aux [] lst
(* โโ Tests โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ *)
let () =
assert (decode [] = []);
assert (decode [One 'a'; One 'b'] = ['a'; 'b']);
assert (decode [Many (3, 'x')] = ['x'; 'x'; 'x']);
assert (decode [Many (3,'a'); One 'b'; Many (2,'c')] = ['a';'a';'a';'b';'c';'c']);
assert (decode_recursive [Many (2,'x'); One 'y'] = ['x';'x';'y']);
assert (decode_tr [Many (3,'a'); One 'b'] = ['a';'a';'a';'b']);
print_endline "โ Decode RLE tests passed"