use super::intcode;\r
use itertools::Itertools;\r
-use std::sync::mpsc::{ self, Sender, Receiver };\r
-use std::thread::{ self, JoinHandle };\r
+use std::sync::{ Arc, Barrier, mpsc::{ self, Sender, Receiver }, atomic::{ AtomicI64, Ordering } };\r
+use threadpool::ThreadPool;\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
// 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
+ self.output_channel.send(value).unwrap_or_default();\r
}\r
}\r
\r
-fn last_thruster_signal_with_feedback_loop(code: &[i64], phase_setting: &[i64]) -> i64 {\r
+fn last_thruster_signal_with_feedback_loop(code: &[i64], phase_setting: &[i64], pool: &ThreadPool) -> i64 {\r
let n = phase_setting.len();\r
\r
let mut senders = Vec::<Sender<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
+ s.send(phase_setting[i]).unwrap_or_default();\r
+ if i == 0 { s.send(0).unwrap_or_default(); }\r
\r
senders.insert(if i == 0 { 0 } else { i - 1 }, s);\r
receivers.push(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 { input_channel: receiver, output_channel: sender, last_produced_value: 0 };\r
- intcode::execute_op_code_with_custom_io(&code_copy, &mut stage);\r
- stage.last_produced_value\r
- }\r
- )\r
+ let result = Arc::new(AtomicI64::new(0));\r
+ let barrier = Arc::new(Barrier::new(2));\r
+\r
+ for (i, (receiver, sender)) in channels.drain(..).enumerate() {\r
+ let code_copy = Vec::<i64>::from(code);\r
+ let barrier = barrier.clone();\r
+ let result = result.clone();\r
+\r
+ pool.execute(\r
+ move || {\r
+ let mut stage = Stage { input_channel: receiver, output_channel: sender, last_produced_value: 0 };\r
+ intcode::execute_op_code_with_custom_io(&code_copy, &mut stage);\r
+ if i == 4 {\r
+ result.store(stage.last_produced_value, Ordering::Relaxed);\r
+ barrier.wait();\r
}\r
- )\r
- .collect();\r
+ }\r
+ )\r
+ }\r
\r
- join_handles.pop().unwrap().join().unwrap()\r
+ barrier.wait();\r
+ result.load(Ordering::Relaxed)\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
+ let pool = ThreadPool::new(5);\r
+ (5i64 ..= 9i64).permutations(5).map(|phase_setting| last_thruster_signal_with_feedback_loop(&code, &phase_setting, &pool)).max().unwrap()\r
}\r
\r
#[cfg(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
+ let pool = ThreadPool::new(5);\r
+ assert_eq!(last_thruster_signal_with_feedback_loop(&code, &phase_setting, &pool), 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), 18_216);\r
+ let pool = ThreadPool::new(5);\r
+ assert_eq!(last_thruster_signal_with_feedback_loop(&code, &phase_setting, &pool), 18_216);\r
}\r
}
\ No newline at end of file