1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
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<u8> {
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<T: AsRef<str>>(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<T: AsRef<str>>(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);
}
}
|