4343//! [`iter_unsigned`]: ParseOps::iter_unsigned
4444use crate :: util:: parse:: * ;
4545use crate :: util:: thread:: * ;
46- use std:: sync:: Mutex ;
46+
47+ type Pair = ( usize , u64 ) ;
4748
4849pub struct Monkey {
4950 items : Vec < u64 > ,
@@ -59,19 +60,8 @@ pub enum Operation {
5960 Add ( u64 ) ,
6061}
6162
62- type Pair = ( usize , u64 ) ;
6363type Business = [ u64 ; 8 ] ;
6464
65- struct Shared < ' a > {
66- monkeys : & ' a [ Monkey ] ,
67- mutex : Mutex < Exclusive > ,
68- }
69-
70- struct Exclusive {
71- pairs : Vec < Pair > ,
72- business : Business ,
73- }
74-
7565/// Extract each Monkey's info from the flavor text. With the exception of the lines starting
7666/// `Operation` we are only interested in the numbers on each line.
7767pub fn parse ( input : & str ) -> Vec < Monkey > {
@@ -102,7 +92,7 @@ pub fn part2(input: &[Monkey]) -> u64 {
10292}
10393
10494/// Convenience wrapper to reuse common logic between part one and two.
105- fn solve ( monkeys : & [ Monkey ] , play : impl Fn ( & [ Monkey ] , Vec < Pair > ) -> Business ) -> u64 {
95+ fn solve ( monkeys : & [ Monkey ] , play : impl Fn ( & [ Monkey ] , & [ Pair ] ) -> Business ) -> u64 {
10696 let mut pairs = Vec :: new ( ) ;
10797
10898 for ( from, monkey) in monkeys. iter ( ) . enumerate ( ) {
@@ -111,16 +101,16 @@ fn solve(monkeys: &[Monkey], play: impl Fn(&[Monkey], Vec<Pair>) -> Business) ->
111101 }
112102 }
113103
114- let mut business = play ( monkeys, pairs) ;
104+ let mut business = play ( monkeys, & pairs) ;
115105 business. sort_unstable ( ) ;
116106 business. iter ( ) . rev ( ) . take ( 2 ) . product ( )
117107}
118108
119109/// Play 20 rounds dividing the worry level by 3 each inspection.
120- fn sequential ( monkeys : & [ Monkey ] , pairs : Vec < Pair > ) -> Business {
110+ fn sequential ( monkeys : & [ Monkey ] , pairs : & [ Pair ] ) -> Business {
121111 let mut business = [ 0 ; 8 ] ;
122112
123- for pair in pairs {
113+ for & pair in pairs {
124114 let extra = play ( monkeys, 20 , |x| x / 3 , pair) ;
125115 business. iter_mut ( ) . enumerate ( ) . for_each ( |( i, b) | * b += extra[ i] ) ;
126116 }
@@ -129,31 +119,21 @@ fn sequential(monkeys: &[Monkey], pairs: Vec<Pair>) -> Business {
129119}
130120
131121/// Play 10,000 rounds adjusting the worry level modulo the product of all the monkey's test values.
132- fn parallel ( monkeys : & [ Monkey ] , pairs : Vec < Pair > ) -> Business {
133- let shared = Shared { monkeys, mutex : Mutex :: new ( Exclusive { pairs, business : [ 0 ; 8 ] } ) } ;
134-
122+ fn parallel ( monkeys : & [ Monkey ] , pairs : & [ Pair ] ) -> Business {
135123 // Use as many cores as possible to parallelize the calculation.
136- spawn ( | | worker ( & shared ) ) ;
124+ let result = spawn_parallel_iterator ( pairs , |iter | worker ( monkeys , iter ) ) ;
137125
138- shared. mutex . into_inner ( ) . unwrap ( ) . business
126+ let mut business = [ 0 ; 8 ] ;
127+ for extra in result. into_iter ( ) . flatten ( ) {
128+ business. iter_mut ( ) . zip ( extra) . for_each ( |( b, e) | * b += e) ;
129+ }
130+ business
139131}
140132
141133/// Multiple worker functions are executed in parallel, one per thread.
142- fn worker ( shared : & Shared < ' _ > ) {
143- let product: u64 = shared. monkeys . iter ( ) . map ( |m| m. test ) . product ( ) ;
144-
145- loop {
146- // Take an item from the queue until empty, using the mutex to allow access
147- // to a single thread at a time.
148- let Some ( pair) = shared. mutex . lock ( ) . unwrap ( ) . pairs . pop ( ) else {
149- break ;
150- } ;
151-
152- let extra = play ( shared. monkeys , 10000 , |x| x % product, pair) ;
153-
154- let mut exclusive = shared. mutex . lock ( ) . unwrap ( ) ;
155- exclusive. business . iter_mut ( ) . enumerate ( ) . for_each ( |( i, b) | * b += extra[ i] ) ;
156- }
134+ fn worker ( monkeys : & [ Monkey ] , iter : ParIter < ' _ , Pair > ) -> Vec < Business > {
135+ let product: u64 = monkeys. iter ( ) . map ( |m| m. test ) . product ( ) ;
136+ iter. map ( |& pair| play ( monkeys, 10000 , |x| x % product, pair) ) . collect ( )
157137}
158138
159139/// Play an arbitrary number of rounds for a single item.
0 commit comments