Add day 8 part 2 solution

This commit is contained in:
Wesley Moore 2017-12-10 19:22:58 +11:00
parent 37bef8869f
commit e608483ef0
2 changed files with 109 additions and 58 deletions

View file

@ -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? 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).

View file

@ -3,15 +3,29 @@ use std::fs::File;
use std::collections::HashMap; use std::collections::HashMap;
use std::str::FromStr; use std::str::FromStr;
type Registers = HashMap<String, i64>; pub struct RegisterMachine {
registers: HashMap<String, i64>,
max_seen: i64
}
fn main() { impl RegisterMachine {
let mut input = String::new(); pub fn new() -> Self {
let mut file = File::open("input").expect("unable to open input file"); RegisterMachine {
file.read_to_string(&mut input).expect("error reading input"); registers: HashMap::new(),
max_seen: 0
}
}
let max = max_value(&eval(&input)); pub fn max(&self) -> i64 {
println!("{}", max); *self.registers.values().max().unwrap()
}
pub fn registers(&self) -> &HashMap<String, i64> {
&self.registers
}
pub fn max_seen(&self) -> i64 {
self.max_seen
} }
fn eval_cond(lhs: i64, cond: &str, rhs: i64) -> bool { fn eval_cond(lhs: i64, cond: &str, rhs: i64) -> bool {
@ -26,7 +40,7 @@ fn eval_cond(lhs: i64, cond: &str, rhs: i64) -> bool {
} }
} }
fn eval_line(registers: &mut Registers, line: &str) { fn eval_line(&mut self, line: &str) {
let tokens = line.split_whitespace().collect::<Vec<_>>(); let tokens = line.split_whitespace().collect::<Vec<_>>();
// b inc 5 if a > 1 // b inc 5 if a > 1
@ -37,32 +51,38 @@ fn eval_line(registers: &mut Registers, line: &str) {
let cond_op = tokens[5]; let cond_op = tokens[5];
let cond_operand = i64::from_str(tokens[6]).expect("cond operand is not a number"); 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 RegisterMachine::eval_cond(self.registers.get(cond_reg).map(|val| *val).unwrap_or(0), cond_op, cond_operand) {
if !registers.contains_key(register) { if !self.registers.contains_key(register) {
registers.insert(register.to_owned(), 0); self.registers.insert(register.to_owned(), 0);
} }
let register_val = registers.get_mut(register).unwrap(); let register_val = self.registers.get_mut(register).unwrap();
match op { match op {
"inc" => *register_val += op_operand, "inc" => *register_val += op_operand,
"dec" => *register_val -= op_operand, "dec" => *register_val -= op_operand,
_ => panic!("unknown operation, '{}'", op) _ => panic!("unknown operation, '{}'", op)
} }
self.max_seen = self.max_seen.max(*register_val)
} }
} }
fn eval(input: &str) -> Registers { fn eval(&mut self, input: &str) {
let mut registers = HashMap::new();
for line in input.lines() { for line in input.lines() {
eval_line(&mut registers, line); self.eval_line(line);
}
}
} }
registers 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 mut machine = RegisterMachine::new();
machine.eval(&input);
println!("Part 1: {}", machine.max());
println!("Part 2: {}", machine.max_seen());
fn max_value(registers: &Registers) -> i64 {
*registers.values().max().unwrap()
} }
#[test] #[test]
@ -76,14 +96,42 @@ fn test_eval() {
expected.insert("a".to_owned(), 1); expected.insert("a".to_owned(), 1);
expected.insert("c".to_owned(), -10); 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] #[test]
fn test_max_value() { fn test_max_value() {
let mut registers = HashMap::new(); 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";
registers.insert("a".to_owned(), 1); let mut expected = HashMap::new();
registers.insert("c".to_owned(), -10);
assert_eq!(max_value(&registers), 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);
} }