aboutsummaryrefslogtreecommitdiff
path: root/src/rle.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/rle.rs')
-rw-r--r--src/rle.rs89
1 files changed, 89 insertions, 0 deletions
diff --git a/src/rle.rs b/src/rle.rs
new file mode 100644
index 0000000..f6d1e05
--- /dev/null
+++ b/src/rle.rs
@@ -0,0 +1,89 @@
1pub trait RLE {
2 type Data;
3 fn compress(&self) -> Vec<Run<Self::Data>>;
4 fn decompress(runs: Vec<Run<Self::Data>>) -> Vec<Self::Data>;
5}
6
7pub type Run<T> = (T, usize);
8
9impl<T> RLE for Vec<T>
10where
11 T: Clone + PartialEq,
12{
13 type Data = T;
14 fn compress(&self) -> Vec<Run<Self::Data>> {
15 let mut runs = vec![];
16 if self.is_empty() {
17 return runs;
18 }
19 let mut idx = 0;
20 loop {
21 let first = &self[idx];
22 let run_length = self[idx..].iter().take_while(|&item| item == first).count();
23
24 runs.push((first.clone(), run_length));
25
26 idx += run_length;
27 if idx > self.len() - 1 {
28 break;
29 }
30 }
31 runs
32 }
33 fn decompress(runs: Vec<Run<Self::Data>>) -> Vec<Self::Data> {
34 runs.into_iter()
35 .map(|(item, size)| vec![item; size])
36 .flatten()
37 .collect()
38 }
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44 #[test]
45 fn singleton() {
46 let data = "a".chars().collect::<Vec<_>>();
47 assert_eq!(Vec::<char>::compress(&data), vec![('a', 1),]);
48 }
49 #[test]
50 fn identity() {
51 let data = "aabbccddaabbaa".chars().collect::<Vec<_>>();
52 assert_eq!(Vec::<char>::decompress(data.compress()), data);
53 }
54 #[test]
55 fn repeated_singleton() {
56 let data = "aaaaaaaaaaaaa".chars().collect::<Vec<_>>();
57 assert_eq!(Vec::<char>::compress(&data), vec![('a', 13),]);
58 }
59 #[test]
60 fn empty_runs() {
61 let data = "".chars().collect::<Vec<_>>();
62 assert!(data.compress().is_empty());
63 }
64 #[test]
65 fn empty_decompress() {
66 assert!(Vec::<char>::decompress(vec![]).is_empty());
67 }
68 #[test]
69 fn check_runs1() {
70 let data = "aaaabbbbcccc".chars().collect::<Vec<_>>();
71 assert_eq!(data.compress(), vec![('a', 4), ('b', 4), ('c', 4)]);
72 }
73 #[test]
74 fn check_runs2() {
75 let data = "aabbccddaabbaa".chars().collect::<Vec<_>>();
76 assert_eq!(
77 data.compress(),
78 vec![
79 ('a', 2),
80 ('b', 2),
81 ('c', 2),
82 ('d', 2),
83 ('a', 2),
84 ('b', 2),
85 ('a', 2)
86 ]
87 );
88 }
89}