+use super::intcode;\r
+use itertools::Itertools;\r
+use std::sync::mpsc::{ self, Sender, Receiver };\r
+use std::thread::{ self, JoinHandle };\r
\r
+fn last_thruster_signal(code: &[i64], phase_setting: &[i64]) -> i64 {\r
+ phase_setting.iter().fold(0, |last_output, input| intcode::execute_op_code(&code, &[*input, last_output])[0])\r
+}\r
\r
+pub fn find_largest_last_thruster_signal(code: &[i64]) -> i64 {\r
+ (0i64 ..= 4i64).permutations(5).map(|phase_setting| last_thruster_signal(&code, &phase_setting)).max().unwrap()\r
+}\r
+\r
+struct Stage {\r
+ input_channel: mpsc::Receiver<i64>,\r
+ output_channel: mpsc::Sender<i64>,\r
+ last_produced_value: i64\r
+}\r
+\r
+impl Stage {\r
+ fn new(input_channel: mpsc::Receiver<i64>, output_channel: mpsc::Sender<i64>) -> Self {\r
+ Stage { input_channel, output_channel, last_produced_value: 0 }\r
+ }\r
+}\r
+\r
+impl intcode::IO for Stage {\r
+ // May block.\r
+ fn read(&mut self) -> i64 {\r
+ match self.input_channel.recv() {\r
+ Ok(value) => value,\r
+ Err(_) => 0\r
+ }\r
+ }\r
+\r
+ // Send to the output channel.\r
+ fn write(&mut self, value: i64) {\r
+ self.last_produced_value = value;\r
+ self.output_channel.send(value);\r
+ }\r
+}\r
+\r
+fn last_thruster_signal_with_feedback_loop(code: &[i64], phase_setting: &[i64]) -> i64 {\r
+ let n = phase_setting.len();\r
+\r
+ let mut senders = Vec::<Sender<i64>>::new();\r
+ let mut receivers = Vec::<Receiver<i64>>::new();\r
+\r
+ for (i, (s, r)) in (0 .. n).map(|i| (i, mpsc::channel::<i64>())) {\r
+ // Initial values.\r
+ s.send(phase_setting[i]);\r
+ if i == 0 { s.send(0); }\r
+\r
+ senders.insert(if i == 0 { 0 } else { i - 1 }, s);\r
+ receivers.push(r);\r
+ }\r
+\r
+ // Prepare each pair of received and sender for the each stages.\r
+ let mut channels: Vec<(Receiver<i64>, Sender<i64>)> = receivers.drain(..).zip(senders.drain(..)).collect();\r
+\r
+ let mut join_handles: Vec<JoinHandle<i64>> =\r
+ channels\r
+ .drain(..)\r
+ .map(\r
+ |(receiver, sender)| {\r
+ let code_copy = Vec::<i64>::from(code);\r
+ thread::spawn(\r
+ move || {\r
+ let mut stage = Stage::new(receiver, sender);\r
+ intcode::execute_op_code_with_custom_io(&code_copy, &mut stage);\r
+ stage.last_produced_value\r
+ }\r
+ )\r
+ }\r
+ )\r
+ .collect();\r
+\r
+ join_handles.pop().unwrap().join().unwrap()\r
+}\r
+\r
+pub fn find_largest_last_thruster_signal_with_feedback_loop(code: &[i64]) -> i64 {\r
+ (5i64 ..= 9i64).permutations(5).map(|phase_setting| last_thruster_signal_with_feedback_loop(&code, &phase_setting)).max().unwrap()\r
+}\r
\r
#[cfg(test)]\r
mod tests {\r
+ use super::*;\r
\r
#[test]\r
- fn part1 () {\r
+ fn part1_sample_1() {\r
+ let code = vec![3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0];\r
+ let phase_setting = [4,3,2,1,0];\r
+ assert_eq!(last_thruster_signal(&code, &phase_setting), 43210);\r
+ }\r
\r
+ #[test]\r
+ fn part1_sample_2() {\r
+ let code = 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];\r
+ let phase_setting = [0,1,2,3,4];\r
+ assert_eq!(last_thruster_signal(&code, &phase_setting), 54321);\r
+ }\r
+\r
+ #[test]\r
+ fn part1_sample_3() {\r
+ let code = 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];\r
+ let phase_setting = [1,0,4,3,2];\r
+ assert_eq!(last_thruster_signal(&code, &phase_setting), 65210);\r
+ }\r
+\r
+ #[test]\r
+ fn part2_sample_1() {\r
+ let code = 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];\r
+ let phase_setting = [9,8,7,6,5];\r
+ assert_eq!(last_thruster_signal_with_feedback_loop(&code, &phase_setting), 139_629_729);\r
+ }\r
+\r
+ #[test]\r
+ fn part2_sample_2() {\r
+ let code = 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];\r
+ let phase_setting = [9,7,8,5,6];\r
+ assert_eq!(last_thruster_signal_with_feedback_loop(&code, &phase_setting), 18216);\r
}\r
}
\ No newline at end of file