diff --git a/aoc2020/src/day08.rs b/aoc2020/src/day08.rs index ef45586..e1c2c96 100644 --- a/aoc2020/src/day08.rs +++ b/aoc2020/src/day08.rs @@ -9,6 +9,7 @@ pub fn run() -> aoc::Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -27,6 +28,34 @@ fn part1(input: &str) -> aoc::Result { }) } +fn part2(input: &str) -> aoc::Result { + let instructions = input + .lines() + .map(|line| line.parse()) + .collect::>>()?; + + for idx in 0..instructions.len() { + let mut instructions = instructions.clone(); + + match instructions[idx] { + Instruction::Acc(_) => continue, + Instruction::Jmp(offset) => instructions[idx] = Instruction::Nop(offset), + Instruction::Nop(offset) => instructions[idx] = Instruction::Jmp(offset), + }; + + let mut interpreter = Interpreter::new(instructions); + + match interpreter.run() { + ExitStatus::InfiniteLoop(_) => continue, + ExitStatus::End(value) => return Ok(value), + } + } + + Err(err!( + "interpreter always had an infinite loop, no solution found" + )) +} + struct Interpreter { idx: usize, accumulator: i64, @@ -54,7 +83,7 @@ impl Interpreter { self.idx += 1; } Instruction::Jmp(offset) => self.idx = self.idx.wrapping_add(offset as usize), - Instruction::Nop => self.idx += 1, + Instruction::Nop(_) => self.idx += 1, } } @@ -69,14 +98,15 @@ impl Interpreter { self.step(); } - return ExitStatus::End(self.accumulator); + ExitStatus::End(self.accumulator) } } +#[derive(Clone)] enum Instruction { Acc(i64), Jmp(i64), - Nop, + Nop(i64), } impl std::str::FromStr for Instruction { @@ -93,7 +123,7 @@ impl std::str::FromStr for Instruction { Ok(match inst { "acc" => Self::Acc(arg), "jmp" => Self::Jmp(arg), - "nop" => Self::Nop, + "nop" => Self::Nop(arg), _ => return Err(err!("unrecognized instruction `{}`", inst)), }) } @@ -114,4 +144,14 @@ mod tests { fn part1_real() { assert_eq!(part1(INPUT).unwrap(), 1675); } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 8); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 1532); + } }