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}