Skip to main content

year2017/
day08.rs

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