11//! # Playground
22use crate :: util:: iter:: * ;
33use crate :: util:: parse:: * ;
4+ use crate :: util:: thread:: * ;
45
5- type Box = [ u64 ; 3 ] ;
6- type Pair = ( usize , usize , u64 ) ;
7- type Input = ( Vec < Box > , Vec < Pair > ) ;
6+ type Box = [ usize ; 3 ] ;
7+ type Pair = ( u16 , u16 , usize ) ;
8+ type Input = ( Vec < Box > , Vec < Vec < Vec < Pair > > > ) ;
89
910struct Node {
1011 parent : usize ,
1112 size : usize ,
1213}
1314
15+ const BUCKETS : usize = 5 ;
16+ const SIZE : usize = 10_000 * 10_000 ;
17+
1418pub fn parse ( input : & str ) -> Input {
15- let boxes: Vec < _ > = input. iter_unsigned :: < u64 > ( ) . chunk :: < 3 > ( ) . collect ( ) ;
16- let mut pairs = Vec :: with_capacity ( boxes. len ( ) * ( boxes. len ( ) - 1 ) ) ;
19+ let boxes: Vec < _ > = input. iter_unsigned :: < usize > ( ) . chunk :: < 3 > ( ) . collect ( ) ;
20+ let items: Vec < _ > = ( 0 ..boxes. len ( ) ) . collect ( ) ;
21+ let mut buckets = vec ! [ vec![ ] ; BUCKETS ] ;
1722
18- for ( i, & v1) in boxes. iter ( ) . enumerate ( ) {
19- for ( j, & v2) in boxes. iter ( ) . enumerate ( ) . skip ( i + 1 ) {
20- let dx = v1[ 0 ] . abs_diff ( v2[ 0 ] ) ;
21- let dy = v1[ 1 ] . abs_diff ( v2[ 1 ] ) ;
22- let dz = v1[ 2 ] . abs_diff ( v2[ 2 ] ) ;
23- let distance = dx * dx + dy * dy + dz * dz;
24- pairs. push ( ( i, j, distance) ) ;
23+ for result in spawn_parallel_iterator ( & items, |iter| worker ( & boxes, iter) ) {
24+ for ( bucket, pairs) in buckets. iter_mut ( ) . zip ( result) {
25+ bucket. push ( pairs) ;
2526 }
2627 }
2728
28- pairs. sort_unstable_by_key ( |& ( .., distance) | distance) ;
29- ( boxes, pairs)
29+ ( boxes, buckets)
3030}
3131
3232pub fn part1 ( input : & Input ) -> usize {
3333 part1_testable ( input, 1000 )
3434}
3535
3636pub fn part1_testable ( input : & Input , limit : usize ) -> usize {
37- let ( boxes, pairs ) = input;
37+ let ( boxes, buckets ) = input;
3838 let mut nodes: Vec < _ > = ( 0 ..boxes. len ( ) ) . map ( |i| Node { parent : i, size : 1 } ) . collect ( ) ;
3939
40- for & ( i, j, ..) in pairs . iter ( ) . take ( limit) {
41- union ( & mut nodes, i, j) ;
40+ for ( i, j, ..) in flatten ( buckets ) . take ( limit) {
41+ union ( & mut nodes, i as usize , j as usize ) ;
4242 }
4343
4444 nodes. sort_unstable_by_key ( |node| node. size ) ;
4545 nodes. iter ( ) . rev ( ) . take ( 3 ) . map ( |node| node. size ) . product ( )
4646}
4747
48- pub fn part2 ( input : & Input ) -> u64 {
49- let ( boxes, pairs ) = input;
48+ pub fn part2 ( input : & Input ) -> usize {
49+ let ( boxes, buckets ) = input;
5050 let mut nodes: Vec < _ > = ( 0 ..boxes. len ( ) ) . map ( |i| Node { parent : i, size : 1 } ) . collect ( ) ;
5151
52- for & ( i, j, ..) in pairs {
52+ for ( i, j, ..) in flatten ( buckets) {
53+ let ( i, j) = ( i as usize , j as usize ) ;
54+
5355 if union ( & mut nodes, i, j) == boxes. len ( ) {
5456 return boxes[ i] [ 0 ] * boxes[ j] [ 0 ] ;
5557 }
@@ -58,6 +60,34 @@ pub fn part2(input: &Input) -> u64 {
5860 unreachable ! ( )
5961}
6062
63+ fn worker ( boxes : & [ Box ] , iter : ParIter < ' _ , usize > ) -> Vec < Vec < Pair > > {
64+ let mut buckets = vec ! [ vec![ ] ; BUCKETS ] ;
65+
66+ for & i in iter {
67+ let v1 = boxes[ i] ;
68+
69+ for ( j, & v2) in boxes. iter ( ) . enumerate ( ) . skip ( i + 1 ) {
70+ let dx = v1[ 0 ] . abs_diff ( v2[ 0 ] ) ;
71+ let dy = v1[ 1 ] . abs_diff ( v2[ 1 ] ) ;
72+ let dz = v1[ 2 ] . abs_diff ( v2[ 2 ] ) ;
73+ let distance = dx * dx + dy * dy + dz * dz;
74+
75+ let index = ( distance / SIZE ) . min ( BUCKETS - 1 ) ;
76+ buckets[ index] . push ( ( i as u16 , j as u16 , distance) ) ;
77+ }
78+ }
79+
80+ buckets
81+ }
82+
83+ fn flatten ( buckets : & [ Vec < Vec < Pair > > ] ) -> impl Iterator < Item = Pair > {
84+ buckets. iter ( ) . flat_map ( |pairs| {
85+ let mut merged = pairs. concat ( ) ;
86+ merged. sort_unstable_by_key ( |& ( .., distance) | distance) ;
87+ merged
88+ } )
89+ }
90+
6191fn find ( set : & mut [ Node ] , mut x : usize ) -> usize {
6292 while set[ x] . parent != x {
6393 let parent = set[ x] . parent ;
0 commit comments