1use std::collections::HashMap;
2use utils::prelude::*;
3use utils::str::TinyStr4;
4
5#[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]);