advent_of_code/year2017/
day18.rs

1use super::assembly::{NumberValue, Program};
2use crate::input::Input;
3
4pub fn solve(input: &Input) -> Result<NumberValue, String> {
5    let mut program_zero = Program::parse(input.text)?;
6    if input.is_part_one() {
7        program_zero.run_until_recover(None);
8        Ok(program_zero.last_played_frequency)
9    } else {
10        let mut program_one = program_zero.clone();
11
12        // "Each program also has its own program ID (one 0 and the other 1);
13        // the register p should begin with this value."
14        program_zero.registers[(b'p' - b'a') as usize] = 0;
15        program_one.registers[(b'p' - b'a') as usize] = 1;
16
17        loop {
18            if !program_zero.terminated {
19                program_zero.run_until_recover(Some(&mut program_one.input_queue));
20            }
21            if !program_one.terminated {
22                program_one.run_until_recover(Some(&mut program_zero.input_queue));
23            }
24
25            if (program_zero.terminated && program_one.terminated)
26                || (program_zero.input_queue.is_empty() && program_one.input_queue.is_empty())
27            {
28                // Both programs terminated, or both programs deadlocking.
29                break;
30            }
31        }
32
33        Ok(program_one.sent_value_count)
34    }
35}
36
37#[test]
38pub fn tests() {
39    use crate::input::{test_part_one, test_part_two};
40
41    let example_input = "snd 1
42snd 2
43snd p
44rcv a
45rcv b
46rcv c
47rcv d";
48    test_part_two!(example_input => 3);
49
50    let real_input = include_str!("day18_input.txt");
51    test_part_one!(real_input => 3423);
52    test_part_two!(real_input => 7493);
53}