From e608483ef09e164a0af0295fb18dabf3fbcf9472 Mon Sep 17 00:00:00 2001 From: Wesley Moore Date: Sun, 10 Dec 2017 19:22:58 +1100 Subject: [PATCH] Add day 8 part 2 solution --- 2017/day/8/problem.txt | 3 + 2017/day/8/src/main.rs | 164 ++++++++++++++++++++++++++--------------- 2 files changed, 109 insertions(+), 58 deletions(-) diff --git a/2017/day/8/problem.txt b/2017/day/8/problem.txt index 46e802e..087e3a9 100644 --- a/2017/day/8/problem.txt +++ b/2017/day/8/problem.txt @@ -22,3 +22,6 @@ You might also encounter <= (less than or equal to) or != (not equal to). Howeve What is the largest value in any register after completing the instructions in your puzzle input? +--- Part Two --- + +To be safe, the CPU also needs to know the highest value held in any register during this process so that it can decide how much memory to allocate to these operations. For example, in the above instructions, the highest value ever held was 10 (in register c after the third instruction was evaluated). diff --git a/2017/day/8/src/main.rs b/2017/day/8/src/main.rs index e4c590b..6a7a156 100644 --- a/2017/day/8/src/main.rs +++ b/2017/day/8/src/main.rs @@ -3,66 +3,86 @@ use std::fs::File; use std::collections::HashMap; use std::str::FromStr; -type Registers = HashMap; +pub struct RegisterMachine { + registers: HashMap, + max_seen: i64 +} + +impl RegisterMachine { + pub fn new() -> Self { + RegisterMachine { + registers: HashMap::new(), + max_seen: 0 + } + } + + pub fn max(&self) -> i64 { + *self.registers.values().max().unwrap() + } + + pub fn registers(&self) -> &HashMap { + &self.registers + } + + pub fn max_seen(&self) -> i64 { + self.max_seen + } + + fn eval_cond(lhs: i64, cond: &str, rhs: i64) -> bool { + match cond { + "==" => lhs == rhs, + "!=" => lhs != rhs, + ">" => lhs > rhs, + ">=" => lhs >= rhs, + "<" => lhs < rhs, + "<=" => lhs <= rhs, + _ => panic!("unknown cond op, '{}'", cond) + } + } + + fn eval_line(&mut self, line: &str) { + let tokens = line.split_whitespace().collect::>(); + + // b inc 5 if a > 1 + let register = tokens[0]; + let op = tokens[1]; + let op_operand = i64::from_str(tokens[2]).expect("op operand is not a number"); + let cond_reg = tokens[4]; + let cond_op = tokens[5]; + let cond_operand = i64::from_str(tokens[6]).expect("cond operand is not a number"); + + if RegisterMachine::eval_cond(self.registers.get(cond_reg).map(|val| *val).unwrap_or(0), cond_op, cond_operand) { + if !self.registers.contains_key(register) { + self.registers.insert(register.to_owned(), 0); + } + + let register_val = self.registers.get_mut(register).unwrap(); + match op { + "inc" => *register_val += op_operand, + "dec" => *register_val -= op_operand, + _ => panic!("unknown operation, '{}'", op) + } + self.max_seen = self.max_seen.max(*register_val) + } + } + + fn eval(&mut self, input: &str) { + for line in input.lines() { + self.eval_line(line); + } + } +} fn main() { let mut input = String::new(); let mut file = File::open("input").expect("unable to open input file"); file.read_to_string(&mut input).expect("error reading input"); - let max = max_value(&eval(&input)); - println!("{}", max); -} + let mut machine = RegisterMachine::new(); + machine.eval(&input); + println!("Part 1: {}", machine.max()); + println!("Part 2: {}", machine.max_seen()); -fn eval_cond(lhs: i64, cond: &str, rhs: i64) -> bool { - match cond { - "==" => lhs == rhs, - "!=" => lhs != rhs, - ">" => lhs > rhs, - ">=" => lhs >= rhs, - "<" => lhs < rhs, - "<=" => lhs <= rhs, - _ => panic!("unknown cond op, '{}'", cond) - } -} - -fn eval_line(registers: &mut Registers, line: &str) { - let tokens = line.split_whitespace().collect::>(); - - // b inc 5 if a > 1 - let register = tokens[0]; - let op = tokens[1]; - let op_operand = i64::from_str(tokens[2]).expect("op operand is not a number"); - let cond_reg = tokens[4]; - let cond_op = tokens[5]; - let cond_operand = i64::from_str(tokens[6]).expect("cond operand is not a number"); - - if eval_cond(registers.get(cond_reg).map(|val| *val).unwrap_or(0), cond_op, cond_operand) { - if !registers.contains_key(register) { - registers.insert(register.to_owned(), 0); - } - - let register_val = registers.get_mut(register).unwrap(); - match op { - "inc" => *register_val += op_operand, - "dec" => *register_val -= op_operand, - _ => panic!("unknown operation, '{}'", op) - } - } -} - -fn eval(input: &str) -> Registers { - let mut registers = HashMap::new(); - - for line in input.lines() { - eval_line(&mut registers, line); - } - - registers -} - -fn max_value(registers: &Registers) -> i64 { - *registers.values().max().unwrap() } #[test] @@ -76,14 +96,42 @@ fn test_eval() { expected.insert("a".to_owned(), 1); expected.insert("c".to_owned(), -10); - assert_eq!(eval(input), expected); + let mut machine = RegisterMachine::new(); + machine.eval(input); + + assert_eq!(machine.registers(), &expected); } #[test] fn test_max_value() { - let mut registers = HashMap::new(); - registers.insert("a".to_owned(), 1); - registers.insert("c".to_owned(), -10); + 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\n"; + let mut expected = HashMap::new(); - assert_eq!(max_value(®isters), 1); + // a is increased by 1 (to 1) because b is less than 5 (it is 0). + // c is decreased by -10 (to 10) because a is now greater than or equal to 1 (it is 1). + // c is increased by -20 (to -10) because c is equal to 10. + expected.insert("a".to_owned(), 1); + expected.insert("c".to_owned(), -10); + + let mut machine = RegisterMachine::new(); + machine.eval(input); + + assert_eq!(machine.max(), 1); +} + +#[test] +fn test_max_seen() { + 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\n"; + let mut expected = HashMap::new(); + + // a is increased by 1 (to 1) because b is less than 5 (it is 0). + // c is decreased by -10 (to 10) because a is now greater than or equal to 1 (it is 1). + // c is increased by -20 (to -10) because c is equal to 10. + expected.insert("a".to_owned(), 1); + expected.insert("c".to_owned(), -10); + + let mut machine = RegisterMachine::new(); + machine.eval(input); + + assert_eq!(machine.max_seen(), 10); }