advent_of_code/year2016/
day09.rs1use crate::input::Input;
2
3fn uncompressed_size(text: &[u8], recursive: bool) -> Result<u64, String> {
4 let error_mapper_uf8 = |_| "Invalid input";
5 let error_mapper_parse = |_| "Invalid input";
6 let mut start_parenthesis_idx = None;
7 let mut uncompressed_len = 0_u64;
8
9 let mut i = 0;
10 while i < text.len() {
11 let c = text[i];
12 if c == b'(' {
13 start_parenthesis_idx = Some(i);
14 } else if c == b')' {
15 if let Some(from) = start_parenthesis_idx {
16 let inside_parenthesis = &text[from + 1..i];
17 let parts = inside_parenthesis
18 .split(|&c| c == b'x')
19 .collect::<Vec<&[u8]>>();
20 if parts.len() != 2 {
21 return Err("Invalid input".into());
22 }
23 let chars_to_take = std::str::from_utf8(parts[0])
24 .map_err(error_mapper_uf8)?
25 .parse::<u64>()
26 .map_err(error_mapper_parse)?;
27 let repetitions = std::str::from_utf8(parts[1])
28 .map_err(error_mapper_uf8)?
29 .parse::<u64>()
30 .map_err(error_mapper_parse)?;
31 uncompressed_len += repetitions
32 * if recursive {
33 uncompressed_size(&text[i + 1..i + 1 + chars_to_take as usize], true)?
34 } else {
35 chars_to_take
36 };
37 i += chars_to_take as usize;
38 start_parenthesis_idx = None;
39 }
40 } else if start_parenthesis_idx.is_none() {
41 uncompressed_len += 1;
42 }
43 i += 1;
44 }
45
46 Ok(uncompressed_len)
47}
48
49pub fn solve(input: &Input) -> Result<u64, String> {
50 let text = input.text.as_bytes();
51 uncompressed_size(text, input.is_part_two())
52}
53
54#[test]
55pub fn tests() {
56 test_part_one!("ADVENT" => 6);
57 test_part_one!("A(1x5)BC" => 7);
58 test_part_one!("(3x3)XYZ" => 9);
59 test_part_one!("A(2x2)BCD(2x2)EFG" => 11);
60
61 test_part_two!("(3x3)XYZ" => 9);
62 test_part_two!("X(8x2)(3x3)ABCY" => 20);
63
64 let real_input = include_str!("day09_input.txt");
65 test_part_one!(real_input => 183_269);
66 test_part_two!(real_input => 11_317_278_863);
67}