pub trait RLE { type Data; fn compress(&self) -> Vec>; fn decompress(runs: Vec>) -> Vec; } pub type Run = (T, usize); impl RLE for Vec where T: Clone + PartialEq, { type Data = T; fn compress(&self) -> Vec> { let mut runs = vec![]; if self.is_empty() { return runs; } let mut idx = 0; loop { let first = &self[idx]; let run_length = self[idx..].iter().take_while(|&item| item == first).count(); runs.push((first.clone(), run_length)); idx += run_length; if idx > self.len() - 1 { break; } } runs } fn decompress(runs: Vec>) -> Vec { runs.into_iter() .map(|(item, size)| vec![item; size]) .flatten() .collect() } } #[cfg(test)] mod tests { use super::*; #[test] fn singleton() { let data = "a".chars().collect::>(); assert_eq!(Vec::::compress(&data), vec![('a', 1),]); } #[test] fn identity() { let data = "aabbccddaabbaa".chars().collect::>(); assert_eq!(Vec::::decompress(data.compress()), data); } #[test] fn repeated_singleton() { let data = "aaaaaaaaaaaaa".chars().collect::>(); assert_eq!(Vec::::compress(&data), vec![('a', 13),]); } #[test] fn empty_runs() { let data = "".chars().collect::>(); assert!(data.compress().is_empty()); } #[test] fn empty_decompress() { assert!(Vec::::decompress(vec![]).is_empty()); } #[test] fn check_runs1() { let data = "aaaabbbbcccc".chars().collect::>(); assert_eq!(data.compress(), vec![('a', 4), ('b', 4), ('c', 4)]); } #[test] fn check_runs2() { let data = "aabbccddaabbaa".chars().collect::>(); assert_eq!( data.compress(), vec![ ('a', 2), ('b', 2), ('c', 2), ('d', 2), ('a', 2), ('b', 2), ('a', 2) ] ); } }