year2018/
day08.rs

1use utils::parser::ParseError;
2use utils::prelude::*;
3
4/// Summing nested node metadata.
5#[derive(Clone, Debug)]
6pub struct Day08 {
7    part1: u32,
8    part2: u32,
9}
10
11impl Day08 {
12    pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
13        let mut iter = parser::u32()
14            .with_consumed()
15            .with_suffix(b' '.or(parser::eof()))
16            .parse_iterator(input);
17
18        let (part1, part2) = Self::parse_node(&mut |name, min_bound, max_bound| {
19            let min_bound = min_bound.unwrap_or(0);
20            let max_bound = max_bound.unwrap_or(u32::MAX);
21            match iter.next() {
22                None => Err(InputError::new(
23                    input,
24                    input.len(),
25                    ParseError::Expected(name),
26                )),
27                Some(Ok((n, pos))) if n < min_bound => Err(InputError::new(
28                    input,
29                    pos,
30                    ParseError::NumberTooSmall(min_bound.into()),
31                )),
32                Some(Ok((n, pos))) if n > max_bound => Err(InputError::new(
33                    input,
34                    pos,
35                    ParseError::NumberTooLarge(max_bound.into()),
36                )),
37                Some(Ok((n, _))) => Ok(n),
38                Some(Err(e)) => Err(e),
39            }
40        })?;
41
42        let remaining = iter.remaining();
43        if !remaining.is_empty() {
44            return Err(InputError::new(input, remaining, ParseError::ExpectedEof()));
45        }
46
47        Ok(Self { part1, part2 })
48    }
49
50    fn parse_node(
51        next: &mut impl FnMut(&'static str, Option<u32>, Option<u32>) -> Result<u32, InputError>,
52    ) -> Result<(u32, u32), InputError> {
53        let children = next("child count", None, Some(16))?;
54        let metadata = next("metadata count", Some(1), None)?;
55
56        let mut part1 = 0;
57        let mut child_values = [0; 16];
58        for i in 0..children {
59            let (p1, p2) = Self::parse_node(next)?;
60            part1 += p1;
61            child_values[i as usize] = p2;
62        }
63
64        let mut part2 = 0;
65        for _ in 0..metadata {
66            let e = next("metadata entry", None, None)?;
67            part1 += e;
68            part2 += child_values
69                .get(e.wrapping_sub(1) as usize)
70                .copied()
71                .unwrap_or(0);
72        }
73
74        if children == 0 {
75            part2 = part1;
76        }
77
78        Ok((part1, part2))
79    }
80
81    #[must_use]
82    pub fn part1(&self) -> u32 {
83        self.part1
84    }
85
86    #[must_use]
87    pub fn part2(&self) -> u32 {
88        self.part2
89    }
90}
91
92examples!(Day08 -> (u32, u32) [
93    {input: "2 3 0 3 10 11 12 1 1 0 1 99 2 1 1 2", part1: 138, part2: 66},
94]);