Created
January 30, 2026 01:02
-
-
Save icub3d/19312b5cddbf57adf5e8daeca04597fd to your computer and use it in GitHub Desktop.
Solution for Advent of Code 2017 Day 8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use std::time::Instant; | |
| use rustc_hash::FxHashMap; | |
| const INPUT: &str = include_str!("inputs/day08.txt"); | |
| enum Modifier { | |
| Increment(isize), | |
| Decrement(isize), | |
| } | |
| impl Modifier { | |
| fn new(what: &str, quantity: &str) -> Self { | |
| match what { | |
| "inc" => Self::Increment(quantity.parse::<isize>().unwrap()), | |
| _ => Self::Decrement(quantity.parse::<isize>().unwrap()), | |
| } | |
| } | |
| fn apply(&self, to: &mut isize) { | |
| match self { | |
| Self::Increment(q) => *to += q, | |
| Self::Decrement(q) => *to -= q, | |
| } | |
| } | |
| } | |
| enum Comparator { | |
| Equal, | |
| NotEqual, | |
| Less, | |
| LessEqual, | |
| Greater, | |
| GreaterEqual, | |
| } | |
| impl Comparator { | |
| fn eval(&self, lhs: isize, rhs: isize) -> bool { | |
| match self { | |
| Comparator::Equal => lhs == rhs, | |
| Comparator::NotEqual => lhs != rhs, | |
| Comparator::Less => lhs < rhs, | |
| Comparator::LessEqual => lhs <= rhs, | |
| Comparator::Greater => lhs > rhs, | |
| Comparator::GreaterEqual => lhs >= rhs, | |
| } | |
| } | |
| } | |
| impl From<&str> for Comparator { | |
| fn from(value: &str) -> Self { | |
| match value { | |
| "==" => Comparator::Equal, | |
| "!=" => Comparator::NotEqual, | |
| "<" => Comparator::Less, | |
| "<=" => Comparator::LessEqual, | |
| ">" => Comparator::Greater, | |
| ">=" => Comparator::GreaterEqual, | |
| _ => panic!("bug"), | |
| } | |
| } | |
| } | |
| struct Condition<'a> { | |
| register: &'a str, | |
| comp: Comparator, | |
| value: isize, | |
| } | |
| impl<'a> Condition<'a> { | |
| fn eval(&self, registers: &FxHashMap<&str, isize>) -> bool { | |
| self.comp | |
| .eval(*registers.get(self.register).unwrap_or(&0), self.value) | |
| } | |
| fn new(register: &'a str, comp: &str, value: &str) -> Self { | |
| Self { | |
| register, | |
| comp: comp.into(), | |
| value: value.parse::<isize>().unwrap(), | |
| } | |
| } | |
| } | |
| struct Instruction<'a> { | |
| register: &'a str, | |
| modifier: Modifier, | |
| condition: Condition<'a>, | |
| } | |
| impl<'a> Instruction<'a> { | |
| fn parse(input: &'a str) -> Self { | |
| let mut parts = input.split_whitespace().filter(|&v| v != "if"); | |
| Instruction { | |
| register: parts.next().unwrap(), | |
| modifier: Modifier::new(parts.next().unwrap(), parts.next().unwrap()), | |
| condition: Condition::new( | |
| parts.next().unwrap(), | |
| parts.next().unwrap(), | |
| parts.next().unwrap(), | |
| ), | |
| } | |
| } | |
| } | |
| fn parse<'a>(input: &'a str) -> Vec<Instruction<'a>> { | |
| input.lines().map(Instruction::parse).collect() | |
| } | |
| fn p1(input: &str) -> isize { | |
| let instructions = parse(input); | |
| let mut registers = FxHashMap::default(); | |
| for instruction in instructions { | |
| if instruction.condition.eval(®isters) { | |
| instruction | |
| .modifier | |
| .apply(registers.entry(instruction.register).or_default()); | |
| } | |
| } | |
| *registers.values().max().unwrap() | |
| } | |
| fn p2(input: &str) -> isize { | |
| let instructions = parse(input); | |
| let mut registers = FxHashMap::default(); | |
| let mut max = isize::MIN; | |
| for instruction in instructions { | |
| if instruction.condition.eval(®isters) { | |
| let reg = registers.entry(instruction.register).or_default(); | |
| instruction.modifier.apply(reg); | |
| max = max.max(*reg); | |
| } | |
| } | |
| max | |
| } | |
| fn main() { | |
| let now = Instant::now(); | |
| let solution = p1(INPUT); | |
| println!("p1 {:?} {}", now.elapsed(), solution); | |
| let now = Instant::now(); | |
| let solution = p2(INPUT); | |
| println!("p2 {:?} {}", now.elapsed(), solution); | |
| } | |
| #[cfg(test)] | |
| mod tests { | |
| use super::*; | |
| #[test] | |
| fn test_p1() { | |
| let input = "b inc 5 if a > 1\na inc 1 if b < 5\nc dec -10 if a >= 1\nc inc -20 if c == 10"; | |
| assert_eq!(p1(input), 1); | |
| } | |
| #[test] | |
| fn test_p2() { | |
| let input = "b inc 5 if a > 1\na inc 1 if b < 5\nc dec -10 if a >= 1\nc inc -20 if c == 10"; | |
| assert_eq!(p2(input), 10); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment