use std::collections::VecDeque; use itertools::Itertools; fn main() { let program = vec![3,8,1001,8,10,8,105,1,0,0,21,38,63,88,97,118,199,280,361,442,99999,3,9,1002,9,3,9,101,2,9,9,1002,9,4,9,4,9,99,3,9,101,3,9,9,102,5,9,9,101,3,9,9,1002,9,3,9,101,3,9,9,4,9,99,3,9,1002,9,2,9,1001,9,3,9,102,3,9,9,101,2,9,9,1002,9,4,9,4,9,99,3,9,102,2,9,9,4,9,99,3,9,102,4,9,9,101,5,9,9,102,2,9,9,101,5,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,99,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,99,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,1,9,9,4,9,99,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,99]; let mut max_storage = 0; let mut max_settings: Vec = Vec::new(); { let settings = vec![0, 1, 2, 3, 4]; // Cheese. for permutation in settings.into_iter().permutations(5) { //println!("{:?}", permutation); let storage = run_amplifiers(&program, permutation.clone()); if storage > max_storage { max_storage = storage; max_settings = permutation.clone(); } } println!("[Part 1] Settings {:?} produced a value of {}", max_settings, max_storage); } { let settings = vec![5, 6, 7, 8, 9]; for permutation in settings.into_iter().permutations(5) { let storage = run_feedback_amplifiers(&program, permutation.clone()); if storage > max_storage { max_storage = storage; max_settings = permutation.clone(); } } println!("[Part 2] Settings {:?} produced a value of {}", max_settings, max_storage); } } fn run_amplifiers(program: &Vec, settings: Vec) -> i32 { let mut storage: i32 = 0; for setting in settings { let mut input = VecDeque::from([setting, storage]); let mut output: Vec = Vec::new(); icc::simulate(&mut program.clone(), &mut input, &mut output, 0); storage = output[0]; } return storage; } fn run_feedback_amplifiers(program: &Vec, settings: Vec) -> i32 { let amplifiers = [ // program, input signal, entrypoint, setting (&mut program.clone(), &mut 0, &mut 0usize, &mut icc::Status::Running), (&mut program.clone(), &mut 0, &mut 0usize, &mut icc::Status::Running), (&mut program.clone(), &mut 0, &mut 0usize, &mut icc::Status::Running), (&mut program.clone(), &mut 0, &mut 0usize, &mut icc::Status::Running), (&mut program.clone(), &mut 0, &mut 0usize, &mut icc::Status::Running), ]; let mut iter: i32 = 0; loop { for (index, setting) in settings.iter().enumerate() { match amplifiers[index].3 { icc::Status::Finished => { if index == 4 { // the output of amplifier 4 is stored on the input of amplifier 0 return *amplifiers[0].1; } continue; }, _ => {} } println!("[Iter {}] Running amplifier {} from instruction {}", iter, index, *amplifiers[index].2); let mut input = if iter == 0 { VecDeque::from([*setting, *amplifiers[index].1]) } else { VecDeque::from([*amplifiers[index].1]) }; let mut output: Vec = Vec::new(); let result = icc::simulate(amplifiers[index].0, &mut input, &mut output, *amplifiers[index].2); match result.status { icc::Status::WaitingForInput => { println!("[Iter {}] Amplifier {} is waiting for input", iter, index); }, _ => {}, } let amp_index = (index+1) % settings.len(); *amplifiers[amp_index].1 = output[0]; println!("[Iter {}] Amplifier {}->{}: {}", iter, index, amp_index, output[0]); *amplifiers[index].2 = result.instruction; *amplifiers[index].3 = result.status; } iter += 1; } } #[cfg(test)] mod tests { use super::*; #[test] fn example_1() { let program = vec![3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0]; let settings = vec![4, 3, 2, 1, 0]; assert_eq!(run_amplifiers(&program, settings), 43210); } #[test] fn example_2() { let program = vec![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]; let settings = vec![0,1,2,3,4]; assert_eq!(run_amplifiers(&program, settings), 54321); } #[test] fn example_3() { let program = vec![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]; let settings = vec![1,0,4,3,2]; assert_eq!(run_amplifiers(&program, settings), 65210); } #[test] fn part2_example_1() { let program = vec![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]; let settings = vec![9,8,7,6,5]; assert_eq!(run_feedback_amplifiers(&program, settings), 139629729); } #[test] fn part2_example_2() { let program = vec![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]; let settings = vec![9,7,8,5,6]; assert_eq!(run_feedback_amplifiers(&program, settings), 18216); } }