Skip to main content

aoc/year2017/
day08.rs

1//! # I Heard You Like Registers
2//!
3//! Computes both parts in a single pass. Each register name is between one and three letters,
4//! so we use a base 27 index (counting `a` as 1 and a blank space as 0) into a `vec` which is
5//! faster than using a hashmap.
6use crate::util::iter::*;
7use crate::util::parse::*;
8
9type Input = (i32, i32);
10
11pub fn parse(input: &str) -> Input {
12    let mut registers = vec![0; 27 * 27 * 27];
13    let mut part_two = 0;
14
15    for [target, operation, amount, _, source, comparison, threshold] in
16        input.split_ascii_whitespace().chunk::<7>()
17    {
18        let value = registers[to_index(source)];
19        let threshold = threshold.signed();
20
21        let predicate = match comparison {
22            "==" => value == threshold,
23            "!=" => value != threshold,
24            ">=" => value >= threshold,
25            "<=" => value <= threshold,
26            ">" => value > threshold,
27            "<" => value < threshold,
28            _ => unreachable!(),
29        };
30
31        if predicate {
32            let register = &mut registers[to_index(target)];
33            let amount: i32 = amount.signed();
34
35            match operation {
36                "inc" => *register += amount,
37                "dec" => *register -= amount,
38                _ => unreachable!(),
39            }
40
41            part_two = part_two.max(*register);
42        }
43    }
44
45    let part_one = registers.into_iter().max().unwrap();
46    (part_one, part_two)
47}
48
49pub fn part1(input: &Input) -> i32 {
50    input.0
51}
52
53pub fn part2(input: &Input) -> i32 {
54    input.1
55}
56
57fn to_index(s: &str) -> usize {
58    s.bytes().fold(0, |acc, b| 27 * acc + usize::from(b - b'a' + 1))
59}