Run Length Encoding
1. Readme
运行游程编码
实现编码和解码.
游程编码(RLE)是一种简单的数据压缩形式,其中运行的(连续数据元素)仅由一个数据值和计数代替。
例如,我们可以只用 13 字节,就可以 代表原始的 53 个字符.
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB" -> "12WB12W3B24WB"
RLE 允许从压缩数据中,完美地重建原始数据,这使其成为无损数据压缩.
"AABCCCDEEEE" -> "2AB3CD4E" -> "AABCCCDEEEE"
为简单起见,您可以假设未编码的字符串,仅包含字母 A 到 Z(小写或大写)和空格。这样,要编码的数据将永远 不包含 任何数字,并且要解码的数据内的数字始终表示后续字符的计数。
资源
维基百科https://en.wikipedia.org/wiki/Run-length_encoding
2. 开始你的表演
pub fn encode(source: &str) -> String { unimplemented!("Return the run-length encoding of {}.", source); } pub fn decode(source: &str) -> String { unimplemented!("Return the run-length decoding of {}.", source); }
3. 测试代码查看
# #![allow(unused_variables)] #fn main() { // encoding tests #[test] fn test_encode_empty_string() { assert_eq!("", encode("")); } #[test] //#[ignore] fn test_encode_single_characters() { assert_eq!("XYZ", encode("XYZ")); } #[test] //#[ignore] fn test_encode_string_with_no_single_characters() { assert_eq!("2A3B4C", encode("AABBBCCCC")); } #[test] //#[ignore] fn test_encode_single_characters_mixed_with_repeated_characters() { assert_eq!( "12WB12W3B24WB", encode("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB") ); } #[test] //#[ignore] fn test_encode_multiple_whitespace_mixed_in_string() { assert_eq!("2 hs2q q2w2 ", encode(" hsqq qww ")); } #[test] //#[ignore] fn test_encode_lowercase_characters() { assert_eq!("2a3b4c", encode("aabbbcccc")); } // decoding tests #[test] //#[ignore] fn test_decode_empty_string() { assert_eq!("", decode("")); } #[test] //#[ignore] fn test_decode_single_characters_only() { assert_eq!("XYZ", decode("XYZ")); } #[test] //#[ignore] fn test_decode_string_with_no_single_characters() { assert_eq!("AABBBCCCC", decode("2A3B4C")); } #[test] //#[ignore] fn test_decode_single_characters_with_repeated_characters() { assert_eq!( "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB", decode("12WB12W3B24WB") ); } #[test] //#[ignore] fn test_decode_multiple_whitespace_mixed_in_string() { assert_eq!(" hsqq qww ", decode("2 hs2q q2w2 ")); } #[test] //#[ignore] fn test_decode_lower_case_string() { assert_eq!("aabbbcccc", decode("2a3b4c")); } // consistency test #[test] //#[ignore] fn test_consistency() { assert_eq!("zzz ZZ zZ", decode(encode("zzz ZZ zZ").as_str())); } #}
4. 答案
# #![allow(unused_variables)] #fn main() { use std::cmp; pub fn encode(input: &str) -> String { input .chars() .fold( (String::new(), ' ', 0, 1), |(mut acc, last, last_n, pos), c| { // acc = where answer is accumulated // last = last character read // last_n = accum count for last if c == last { if pos == input.len() { // end of string acc += (last_n + 1).to_string().as_str(); acc.push(c); } (acc, last, last_n + 1, pos + 1) } else { if last_n > 1 { acc += last_n.to_string().as_str(); } if last_n > 0 { // ignore initial last (single whitespace) acc.push(last); } if pos == input.len() { // end of string acc.push(c); } (acc, c, 1, pos + 1) } }, ) .0 } pub fn decode(input: &str) -> String { input .chars() .fold((String::new(), 0), |(mut acc, last_n), c| { if let Some(d) = c.to_digit(10) { (acc, 10 * last_n + d) } else { acc += c.to_string().repeat(cmp::max(last_n, 1) as usize).as_str(); (acc, 0) } }) .0 } #}