@@ -24,20 +24,17 @@ function dist(a: Coord3d, b: Coord3d): number {
2424 return Math . sqrt ( ( a . x - b . x ) ** 2 + ( a . y - b . y ) ** 2 + ( a . z - b . z ) ** 2 ) ;
2525}
2626
27- function findCircuits ( boxes : Coord3d [ ] , isTestInput : boolean ) : number {
28- const n = boxes . length ;
29- const k = isTestInput ? Math . floor ( n / 2 ) : n ;
30-
31- // Collect all pairs sorted by distance
27+ function sortedPairs ( boxes : Coord3d [ ] ) : [ number , number , number ] [ ] {
3228 const pairs : [ number , number , number ] [ ] = [ ] ;
33- for ( let i = 0 ; i < n ; i ++ ) {
34- for ( let j = i + 1 ; j < n ; j ++ ) {
29+ for ( let i = 0 ; i < boxes . length ; i ++ ) {
30+ for ( let j = i + 1 ; j < boxes . length ; j ++ ) {
3531 pairs . push ( [ dist ( boxes [ i ] , boxes [ j ] ) , i , j ] ) ;
3632 }
3733 }
38- pairs . sort ( ( a , b ) => a [ 0 ] - b [ 0 ] ) ;
34+ return pairs . sort ( ( a , b ) => a [ 0 ] - b [ 0 ] ) ;
35+ }
3936
40- // Union-Find
37+ function makeUnionFind ( n : number ) {
4138 const parent = Array . from ( { length : n } , ( _ , i ) => i ) ;
4239 const size = new Array ( n ) . fill ( 1 ) ;
4340
@@ -49,19 +46,28 @@ function findCircuits(boxes: Coord3d[], isTestInput: boolean): number {
4946 return x ;
5047 }
5148
52- function union ( a : number , b : number ) {
49+ function union ( a : number , b : number ) : boolean {
5350 a = find ( a ) ; b = find ( b ) ;
54- if ( a === b ) return ;
51+ if ( a === b ) return false ;
5552 if ( size [ a ] < size [ b ] ) [ a , b ] = [ b , a ] ;
5653 parent [ b ] = a ;
5754 size [ a ] += size [ b ] ;
55+ return true ;
5856 }
5957
58+ return { find, union, size } ;
59+ }
60+
61+ function findCircuits ( boxes : Coord3d [ ] , isTestInput : boolean ) : number {
62+ const n = boxes . length ;
63+ const k = isTestInput ? Math . floor ( n / 2 ) : n ;
64+ const pairs = sortedPairs ( boxes ) ;
65+ const { find, union, size } = makeUnionFind ( n ) ;
66+
6067 for ( let i = 0 ; i < k ; i ++ ) {
6168 union ( pairs [ i ] [ 1 ] , pairs [ i ] [ 2 ] ) ;
6269 }
6370
64- // Collect circuit sizes via root nodes
6571 const sizes : number [ ] = [ ] ;
6672 for ( let i = 0 ; i < n ; i ++ ) {
6773 if ( find ( i ) === i ) sizes . push ( size [ i ] ) ;
@@ -73,36 +79,14 @@ function findCircuits(boxes: Coord3d[], isTestInput: boolean): number {
7379
7480function findCircuitsPart2 ( boxes : Coord3d [ ] , _isTestInput : boolean ) : number {
7581 const n = boxes . length ;
76-
77- const pairs : [ number , number , number ] [ ] = [ ] ;
78- for ( let i = 0 ; i < n ; i ++ ) {
79- for ( let j = i + 1 ; j < n ; j ++ ) {
80- pairs . push ( [ dist ( boxes [ i ] , boxes [ j ] ) , i , j ] ) ;
81- }
82- }
83- pairs . sort ( ( a , b ) => a [ 0 ] - b [ 0 ] ) ;
84-
85- const parent = Array . from ( { length : n } , ( _ , i ) => i ) ;
86- const size = new Array ( n ) . fill ( 1 ) ;
87-
88- function find ( x : number ) : number {
89- while ( parent [ x ] !== x ) {
90- parent [ x ] = parent [ parent [ x ] ] ;
91- x = parent [ x ] ;
92- }
93- return x ;
94- }
82+ const pairs = sortedPairs ( boxes ) ;
83+ const { union } = makeUnionFind ( n ) ;
9584
9685 let components = n ;
9786 for ( const [ , i , j ] of pairs ) {
98- const ri = find ( i ) , rj = find ( j ) ;
99- if ( ri === rj ) continue ;
100- const [ big , small ] = size [ ri ] >= size [ rj ] ? [ ri , rj ] : [ rj , ri ] ;
101- parent [ small ] = big ;
102- size [ big ] += size [ small ] ;
103- components -- ;
104- if ( components === 1 ) {
105- return boxes [ i ] . x * boxes [ j ] . x ;
87+ if ( union ( i , j ) ) {
88+ components -- ;
89+ if ( components === 1 ) return boxes [ i ] . x * boxes [ j ] . x ;
10690 }
10791 }
10892
0 commit comments