year2017/
day08.rs

1use std::collections::HashMap;
2use utils::prelude::*;
3
4/// Evaluating conditional add instructions.
5#[derive(Clone, Debug)]
6pub struct Day08 {
7    part1: i32,
8    part2: i32,
9}
10
11impl Day08 {
12    pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
13        let parse_iterator = parser::take_while1(u8::is_ascii_lowercase)
14            .with_suffix(" ")
15            .then(
16                parser::one_of((
17                    parser::i32().with_prefix("inc "),
18                    parser::i32().with_prefix("dec ").map(|x| -x),
19                ))
20                .with_suffix(" if "),
21            )
22            .then(parser::take_while1(u8::is_ascii_lowercase).with_suffix(" "))
23            .then(
24                parser::literal_map!(
25                    "==" => i32::eq as fn(&i32, &i32) -> bool,
26                    "!=" => i32::ne as fn(&i32, &i32) -> bool,
27                    "<=" => i32::le as fn(&i32, &i32) -> bool,
28                    ">=" => i32::ge as fn(&i32, &i32) -> bool,
29                    "<" => i32::lt as fn(&i32, &i32) -> bool,
30                    ">" => i32::gt as fn(&i32, &i32) -> bool,
31                )
32                .with_suffix(" "),
33            )
34            .then(parser::i32())
35            .with_suffix(parser::eol())
36            .parse_iterator(input);
37
38        let mut registers = HashMap::new();
39        let mut max = 0;
40        for item in parse_iterator {
41            let (reg, value, cond_reg, comparison, cond_value) = item?;
42            if comparison(registers.entry(cond_reg).or_insert(0), &cond_value) {
43                let entry = registers.entry(reg).or_insert(0);
44                *entry += value;
45                max = max.max(*entry);
46            }
47        }
48
49        Ok(Self {
50            part1: registers.into_values().max().unwrap_or(0),
51            part2: max,
52        })
53    }
54
55    #[must_use]
56    pub fn part1(&self) -> i32 {
57        self.part1
58    }
59
60    #[must_use]
61    pub fn part2(&self) -> i32 {
62        self.part2
63    }
64}
65
66examples!(Day08 -> (i32, i32) [
67    {
68        input: "b inc 5 if a > 1\n\
69            a inc 1 if b < 5\n\
70            c dec -10 if a >= 1\n\
71            c inc -20 if c == 10",
72        part1: 1,
73        part2: 10
74    },
75]);