1use utils::parser::ParseError;
2use utils::prelude::*;
3
4#[derive(Clone, Debug)]
6pub struct Day09 {
7 part1: u64,
8 part2: u64,
9}
10
11impl Day09 {
12 pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
13 Ok(Self {
14 part1: Self::decompressed_length(input.as_bytes(), false).map_with_input(input)?,
15 part2: Self::decompressed_length(input.as_bytes(), true).map_with_input(input)?,
16 })
17 }
18
19 fn decompressed_length(mut input: &[u8], recursive: bool) -> Result<u64, (ParseError, &[u8])> {
20 let mut len = 0;
21
22 while !input.is_empty() {
23 if input[0] == b'(' {
24 let (characters, repeats);
25 (characters, input) = parser::u32().parse(&input[1..])?;
26 (_, input) = b'x'.parse(input)?;
27 (repeats, input) = parser::u32().parse(input)?;
28 (_, input) = b')'.parse(input)?;
29
30 if input.len() < characters as usize {
31 return Err((
32 ParseError::Custom("insufficient characters after marker"),
33 input,
34 ));
35 }
36
37 let repeated_len = if recursive {
38 Self::decompressed_length(&input[..characters as usize], true)?
39 } else {
40 characters as u64
41 };
42
43 len += repeated_len * repeats as u64;
44 input = &input[characters as usize..];
45 } else {
46 len += 1;
47 input = &input[1..];
48 }
49 }
50
51 Ok(len)
52 }
53
54 #[must_use]
55 pub fn part1(&self) -> u64 {
56 self.part1
57 }
58
59 #[must_use]
60 pub fn part2(&self) -> u64 {
61 self.part2
62 }
63}
64
65examples!(Day09 -> (u64, u64) [
66 {input: "ADVENT", part1: 6},
67 {input: "A(1x5)BC", part1: 7},
68 {input: "(3x3)XYZ", part1: 9, part2: 9},
69 {input: "A(2x2)BCD(2x2)EFG", part1: 11},
70 {input: "(6x1)(1x3)A", part1: 6},
71 {input: "X(8x2)(3x3)ABCY", part1: 18, part2: 20},
72 {input: "(27x12)(20x12)(13x14)(7x10)(1x12)A", part2: 241920},
73 {input: "(25x3)(3x3)ABC(2x3)XY(5x2)PQRSTX(18x9)(3x2)TWO(5x7)SEVEN", part2: 445},
74]);