advent_of_code/year2018/
day21.rs1use super::elfcode::Program;
2use crate::input::Input;
3use std::collections::HashSet;
4
5fn parse(input_string: &str) -> Result<Program, String> {
6 let program = Program::parse(input_string)?;
7 if program.instructions.len() != 31 {
8 return Err("Expected 31 instructions in program".to_string());
9 }
10 Ok(program)
11}
12
13const MAX_INSTRUCTIONS: u64 = 1_000_000;
14
15pub fn solve(input: &Input) -> Result<u64, String> {
16 let mut program = parse(input.text)?;
17 if input.is_part_one() {
18 let mut loop_count = 0;
30 while program.instruction_pointer()? != 29 {
31 program.execute_one_instruction()?;
32
33 loop_count += 1;
34 if loop_count > MAX_INSTRUCTIONS {
35 return Err(format!("Aborted after {loop_count} instructions"));
36 }
37 }
38 Ok(program.registers.values[program.instructions[28].a as usize])
39 } else {
40 let mut seen = HashSet::new();
41 let mut last_value = 0;
42 let mut loop_count = 0;
43 loop {
44 let ip = program.instruction_pointer()?;
45 if ip == 14 {
46 if program.registers.values[program.instructions[13].c as usize] == 0 {
47 program.registers.values[program.instructions[6].c as usize] /= 256;
48 program.registers.values[program.instruction_pointer_index as usize] = 8;
49 }
50 } else if ip == 29 {
51 let value = program.registers.values[program.instructions[28].a as usize];
52 if seen.insert(value) {
53 last_value = value;
54 } else {
55 return Ok(last_value);
56 }
57 }
58 program.execute_one_instruction()?;
59
60 loop_count += 1;
61 if loop_count > MAX_INSTRUCTIONS {
62 return Err(format!("Aborted after {loop_count} instructions"));
63 }
64 }
65 }
66}
67
68#[test]
69fn tests() {
70 use crate::input::{test_part_one, test_part_two};
71 let input = include_str!("day21_input.txt");
72 test_part_one!(input => 7_216_956);
73 test_part_two!(input => 14_596_916);
74}