advent_of_code/year2019/
day07.rs

1use super::int_code::{Program, Word};
2use crate::common::permutation::all_permutations;
3use crate::input::Input;
4use std::cell::RefCell;
5
6pub fn solve(input: &Input) -> Result<i64, String> {
7    let program = Program::parse(input.text)?;
8    let mut phase_settings = if input.is_part_one() {
9        [0, 1, 2, 3, 4]
10    } else {
11        [5, 6, 7, 8, 9]
12    };
13    let mut strongest_signal = 0;
14
15    all_permutations(&mut phase_settings, &mut |permutation: &[Word]| {
16        let mut amplifier_programs = Vec::with_capacity(5);
17        for &phase in permutation.iter() {
18            let mut new_program = program.clone();
19            new_program.input(phase);
20            amplifier_programs.push(RefCell::new(new_program));
21        }
22
23        amplifier_programs[0].borrow_mut().input(0);
24
25        let mut last_signal_output = 0;
26        'outer: loop {
27            for i in 0..5 {
28                let mut current_program = amplifier_programs[i].borrow_mut();
29                let output = current_program.run_for_output_limited(10_000)?;
30
31                if i == 4 {
32                    if let Some(&value) = output.last() {
33                        last_signal_output = value;
34                    }
35                    if input.is_part_one() || current_program.is_halted() {
36                        break 'outer;
37                    }
38                }
39
40                let mut next_program = amplifier_programs[(i + 1) % 5].borrow_mut();
41                for &value in output.iter() {
42                    next_program.input(value);
43                }
44            }
45        }
46
47        strongest_signal = std::cmp::max(strongest_signal, last_signal_output);
48        Ok(())
49    })?;
50
51    Ok(strongest_signal)
52}
53
54#[test]
55pub fn tests() {
56    use crate::input::{test_part_one, test_part_one_error, test_part_two, test_part_two_error};
57
58    test_part_one!("3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0" => 43210);
59    test_part_one!("3,23,3,24,1002,24,10,24,1002,23,-1,23,101,5,23,23,1,24,23,23,4,23,99,0,0"=>54321);
60    test_part_one!("3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0" => 65210);
61
62    test_part_two!("3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5" => 139_629_729);
63    test_part_two!("3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54,-5,54,1105,1,12,1,53,54,53,1008,54,0,55,1001,55,1,55,2,53,55,53,4,53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10" => 18216);
64
65    let real_input = include_str!("day07_input.txt");
66    test_part_one!(real_input => 51679);
67    test_part_two!(real_input => 19_539_216);
68
69    test_part_one_error!("3,-14" => "Bad address: -14");
70    test_part_two_error!("3,448552900448552866" => "Bad address: 448552900448552866");
71}