// Modified Run-Length Encoding โ 99 Problems #11
// Single elements stay unwrapped (One), runs get (count, elem) (Many)
#[derive(Debug, PartialEq, Clone)]
enum Rle<T> {
One(T),
Many(usize, T),
}
/// Pack consecutive duplicates into groups, then encode.
fn pack<T: PartialEq + Clone>(lst: &[T]) -> Vec<Vec<T>> {
let mut result: Vec<Vec<T>> = Vec::new();
for item in lst {
match result.last_mut() {
Some(group) if group.last() == Some(item) => group.push(item.clone()),
_ => result.push(vec![item.clone()]),
}
}
result
}
fn encode<T: PartialEq + Clone>(lst: &[T]) -> Vec<Rle<T>> {
pack(lst)
.into_iter()
.map(|group| {
if group.len() == 1 {
Rle::One(group.into_iter().next().unwrap())
} else {
let len = group.len();
Rle::Many(len, group.into_iter().next().unwrap())
}
})
.collect()
}
/// Direct recursive version without intermediate pack step.
fn encode_direct<T: PartialEq + Clone>(lst: &[T]) -> Vec<Rle<T>> {
let mut result: Vec<Rle<T>> = Vec::new();
for item in lst {
match result.last_mut() {
Some(Rle::Many(n, x)) if x == item => *n += 1,
Some(Rle::One(x)) if x == item => {
let x = x.clone();
*result.last_mut().unwrap() = Rle::Many(2, x);
}
_ => result.push(Rle::One(item.clone())),
}
}
result
}
fn main() {
let input = vec!['a', 'a', 'a', 'b', 'c', 'c', 'a', 'a', 'd', 'e', 'e', 'e', 'e'];
let encoded = encode(&input);
println!("Input: {:?}", input);
println!("Encoded: {:?}", encoded);
let direct = encode_direct(&input);
println!("Direct: {:?}", direct);
let singles = vec!['a', 'b', 'c'];
println!("Singles: {:?}", encode(&singles));
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_encode_empty() {
let empty: Vec<char> = vec![];
assert_eq!(encode(&empty), vec![]);
}
#[test]
fn test_encode_all_single() {
assert_eq!(
encode(&['a', 'b', 'c']),
vec![Rle::One('a'), Rle::One('b'), Rle::One('c')]
);
}
#[test]
fn test_encode_mixed() {
let input = vec!['a', 'a', 'a', 'b', 'c', 'c'];
assert_eq!(
encode(&input),
vec![Rle::Many(3, 'a'), Rle::One('b'), Rle::Many(2, 'c')]
);
}
#[test]
fn test_encode_direct_matches_encode() {
let input = vec!['a', 'a', 'b', 'c', 'c', 'c'];
assert_eq!(encode(&input), encode_direct(&input));
}
}
(* Modified Run-Length Encoding โ 99 Problems #11 *)
(* Single elements stay unwrapped, runs get (count, elem) *)
type 'a rle =
| One of 'a
| Many of int * 'a
(* โโ Pack consecutive duplicates into sublists โโโโโโโโโโโโโ *)
let pack lst =
let rec aux current acc = function
| [] -> List.rev (current :: acc)
| x :: rest ->
match current with
| [] -> aux [x] acc rest
| y :: _ when x = y -> aux (x :: current) acc rest
| _ -> aux [x] (current :: acc) rest
in match lst with
| [] -> []
| h :: t -> aux [h] [] t
(* โโ Modified RLE using pack โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ *)
let encode lst =
pack lst
|> List.map (fun group ->
match group with
| [x] -> One x
| x :: _ -> Many (List.length group, x)
| [] -> failwith "impossible")
(* โโ Direct recursive version โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ *)
let encode_direct lst =
let rec aux count acc = function
| [] -> List.rev acc
| [x] -> List.rev ((if count = 0 then One x else Many (count + 1, x)) :: acc)
| x :: (y :: _ as rest) ->
if x = y then aux (count + 1) acc rest
else
let item = if count = 0 then One x else Many (count + 1, x) in
aux 0 (item :: acc) rest
in aux 0 [] lst
(* โโ Tests โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ *)
let () =
assert (encode [] = []);
assert (encode ['a';'b';'c'] = [One 'a'; One 'b'; One 'c']);
assert (encode ['x';'x';'x'] = [Many (3, 'x')]);
assert (encode ['a';'a';'a';'b';'c';'c'] = [Many (3,'a'); One 'b'; Many (2,'c')]);
assert (encode_direct ['a';'a';'b';'c';'c';'c'] = [Many (2,'a'); One 'b'; Many (3,'c')]);
print_endline "โ Modified RLE tests passed"