6
6
//! This makes the total complexity `O(n³)`, however the calculation for each size is independent
7
7
//! so we can parallelize over multiple threads.
8
8
use crate :: util:: parse:: * ;
9
+ use crate :: util:: thread:: * ;
9
10
use std:: sync:: Mutex ;
10
- use std:: thread;
11
11
12
12
pub struct Result {
13
13
x : usize ,
@@ -38,36 +38,15 @@ pub fn parse(input: &str) -> Vec<Result> {
38
38
}
39
39
40
40
// Use as many cores as possible to parallelize the search.
41
- let threads = thread:: available_parallelism ( ) . unwrap ( ) . get ( ) ;
41
+ // Smaller sizes take more time so keep batches roughly the same effort so that some
42
+ // threads are not finishing too soon and waiting idle, while others are still busy.
43
+ // For example if there are 4 cores, then they will be assigned sizes:
44
+ // * 1, 5, 9, ..
45
+ // * 2, 6, 10, ..
46
+ // * 3, 7, 11, ..
47
+ // * 4, 8, 12, ..
42
48
let mutex = Mutex :: new ( Vec :: new ( ) ) ;
43
-
44
- thread:: scope ( |scope| {
45
- for i in 0 ..threads {
46
- // Shadow references in local variables so that they can be moved into closure.
47
- let sat = & sat;
48
- let mutex = & mutex;
49
-
50
- // Smaller sizes take more time so keep batches roughly the same effort so that some
51
- // threads are not finishing too soon and waiting idle, while others are still busy.
52
- // For example if there are 4 cores, then they will be assigned sizes:
53
- // * 1, 5, 9, ..
54
- // * 2, 6, 10, ..
55
- // * 3, 7, 11, ..
56
- // * 4, 8, 12, ..
57
- scope. spawn ( move || {
58
- let batch: Vec < _ > = ( 1 + i..301 )
59
- . step_by ( threads)
60
- . map ( |size| {
61
- let ( power, x, y) = square ( sat, size) ;
62
- Result { x, y, size, power }
63
- } )
64
- . collect ( ) ;
65
-
66
- mutex. lock ( ) . unwrap ( ) . extend ( batch) ;
67
- } ) ;
68
- }
69
- } ) ;
70
-
49
+ spawn_batches ( ( 1 ..301 ) . collect ( ) , |batch| worker ( batch, & sat, & mutex) ) ;
71
50
mutex. into_inner ( ) . unwrap ( )
72
51
}
73
52
@@ -81,6 +60,18 @@ pub fn part2(input: &[Result]) -> String {
81
60
format ! ( "{x},{y},{size}" )
82
61
}
83
62
63
+ fn worker ( batch : Vec < usize > , sat : & [ i32 ] , mutex : & Mutex < Vec < Result > > ) {
64
+ let result: Vec < _ > = batch
65
+ . into_iter ( )
66
+ . map ( |size| {
67
+ let ( power, x, y) = square ( sat, size) ;
68
+ Result { x, y, size, power }
69
+ } )
70
+ . collect ( ) ;
71
+
72
+ mutex. lock ( ) . unwrap ( ) . extend ( result) ;
73
+ }
74
+
84
75
/// Find the (x,y) coordinates and max power for a square of the specified size.
85
76
fn square ( sat : & [ i32 ] , size : usize ) -> ( i32 , usize , usize ) {
86
77
let mut max_power = i32:: MIN ;
0 commit comments