fn main() { let input = advent::read_lines(8); println!("8a: {}", count_chars_decoding(&input)); println!("8b: {}", count_chars_encoding(&input)); } fn decode_string(word: &str) -> Vec { let mut decoded = Vec::new(); let mut chars = word.chars(); // drop " at beginning assert_eq!(chars.next(), Some('"')); while let Some(c) = chars.next() { if c == '\\' { let next = chars.next().unwrap(); if next == 'x' { let digit1 = chars.next().unwrap().to_digit(16).unwrap(); let digit2 = chars.next().unwrap().to_digit(16).unwrap(); let code = 16 * digit1 + digit2; decoded.push(char::from_u32(code).unwrap() as u8); } else { decoded.push(next as u8); } } else { decoded.push(c as u8); } } // drop " at end assert_eq!(decoded.pop(), Some(34)); decoded } fn count_chars_decoding>(input: &[T]) -> usize { let mut code = 0; let mut values = 0; for line in input { code += line.as_ref().len(); values += decode_string(line.as_ref()).len(); } code - values } fn encode_string(word: &str) -> String { let mut encoded = String::new(); encoded.push('"'); for c in word.chars() { match c { '"' => encoded += "\\\"", '\\' => encoded += "\\\\", rest => encoded.push(rest), } } encoded.push('"'); encoded } fn count_chars_encoding>(input: &[T]) -> usize { let mut code = 0; let mut values = 0; for line in input { code += line.as_ref().len(); values += encode_string(line.as_ref()).len(); } values - code } #[cfg(test)] mod tests { use super::*; #[test] fn test() { let input = [ "\"\"", "\"abc\"", "\"aaa\\\"aaa\"", "\"\\x27\"", ]; assert_eq!(count_chars_decoding(&input), 12); assert_eq!(count_chars_encoding(&input), 19); } }