11import static com .github .pareronia .aoc .IntegerSequence .Range .range ;
22
33import static java .util .Comparator .comparing ;
4- import static java .util .Comparator .reverseOrder ;
5- import static java .util .stream .Collectors .toMap ;
64
75import com .github .pareronia .aoc .StringOps ;
86import com .github .pareronia .aoc .geometry3d .Position3D ;
97import com .github .pareronia .aoc .solution .SolutionBase ;
108
11- import java .util .ArrayList ;
12- import java .util .Collections ;
9+ import java .util .Arrays ;
1310import java .util .List ;
1411
1512@ SuppressWarnings ({"PMD.ClassNamingConventions" , "PMD.NoPackage" })
@@ -29,39 +26,30 @@ public static AoC2025_08 createDebug() {
2926
3027 @ Override
3128 protected Input parseInput (final List <String > inputs ) {
32- final List <Position3D > boxes =
33- inputs .stream ()
34- .map (
35- s -> {
36- final String [] splits = s .split ("," );
37- return Position3D .of (
38- Integer .parseInt (splits [0 ]),
39- Integer .parseInt (splits [1 ]),
40- Integer .parseInt (splits [2 ]));
41- })
29+ final List <Box > boxes =
30+ range (inputs .size ()).stream ().map (i -> Box .fromInput (i , inputs .get (i ))).toList ();
31+ final List <Pair > pairs =
32+ range (boxes .size ()).stream ()
33+ .flatMap (
34+ i ->
35+ range (i + 1 , boxes .size (), 1 ).stream ()
36+ .map (j -> Pair .of (boxes .get (i ), boxes .get (j ))))
37+ .sorted (comparing (Pair ::distance ))
4238 .toList ();
43- final List <Pair > pairs = new ArrayList <>();
44- for (int i = 0 ; i < boxes .size (); i ++) {
45- for (int j = i + 1 ; j < boxes .size (); j ++) {
46- pairs .add (new Pair (i , j , boxes .get (i ).squaredDistance (boxes .get (j ))));
47- }
48- }
49- Collections .sort (pairs , comparing (Pair ::distance ));
5039 return new Input (boxes , pairs );
5140 }
5241
42+ @ SuppressWarnings ("PMD.LawOfDemeter" )
5343 private long solve1 (final Input input , final int size ) {
5444 final DSU dsu = new DSU (input .boxes ().size ());
55- input .pairs ().stream ().limit (size ).forEach (pair -> dsu .unify (pair .first (), pair .second ()));
56- return range (input .boxes ().size ()).stream ()
57- .collect (toMap (i -> i , dsu ::componentSize ))
58- .values ()
59- .stream ()
60- .distinct ()
61- .sorted (reverseOrder ())
62- .limit (3 )
45+ input .pairs ().stream ()
46+ .limit (size )
47+ .forEach (pair -> dsu .unify (pair .first ().idx (), pair .second ().idx ()));
48+ return Arrays .stream (dsu .sz )
49+ .sorted ()
50+ .skip (dsu .sz .length - 3 )
6351 .reduce ((acc , sz ) -> acc * sz )
64- .get ();
52+ .getAsInt ();
6553 }
6654
6755 @ Override
@@ -70,16 +58,20 @@ public Long solvePart1(final Input input) {
7058 }
7159
7260 @ Override
61+ @ SuppressWarnings ("PMD.LawOfDemeter" )
7362 public Long solvePart2 (final Input input ) {
7463 final DSU dsu = new DSU (input .boxes ().size ());
75- for (final Pair pair : input .pairs ()) {
76- dsu .unify (pair .first (), pair .second ());
77- if (dsu .components () == 1 && dsu .componentSize (0 ) == input .boxes ().size ()) {
78- return ((long ) input .boxes ().get (pair .first ()).getX ())
79- * input .boxes ().get (pair .second ()).getX ();
80- }
81- }
82- throw new IllegalStateException ("Unsolvable" );
64+ return input .pairs ().stream ()
65+ .mapToLong (
66+ pair -> {
67+ dsu .unify (pair .first ().idx (), pair .second ().idx ());
68+ return ((long ) pair .first ().position ().getX ())
69+ * pair .second ().position ().getX ();
70+ })
71+ .dropWhile (
72+ x -> dsu .numComponents != 1 || dsu .sz [dsu .find (0 )] != input .boxes ().size ())
73+ .findFirst ()
74+ .orElseThrow ();
8375 }
8476
8577 @ Override
@@ -118,9 +110,27 @@ public static void main(final String[] args) throws Exception {
118110 425,690,689
119111 """ ;
120112
121- record Pair (int first , int second , long distance ) {}
113+ record Box (int idx , Position3D position ) {
114+
115+ public static Box fromInput (final int idx , final String input ) {
116+ final String [] splits = input .split ("," );
117+ return new Box (
118+ idx ,
119+ Position3D .of (
120+ Integer .parseInt (splits [0 ]),
121+ Integer .parseInt (splits [1 ]),
122+ Integer .parseInt (splits [2 ])));
123+ }
124+ }
125+
126+ record Pair (Box first , Box second , long distance ) {
127+
128+ public static Pair of (final Box first , final Box second ) {
129+ return new Pair (first , second , first .position ().squaredDistance (second .position ()));
130+ }
131+ }
122132
123- record Input (List <Position3D > boxes , List <Pair > pairs ) {}
133+ record Input (List <Box > boxes , List <Pair > pairs ) {}
124134
125135 private static class DSU {
126136
@@ -140,48 +150,27 @@ public DSU(final int size) {
140150 }
141151
142152 public int find (final int p ) {
143- int target = p ;
144- int root = target ;
153+ int root = p ;
145154 while (root != id [root ]) {
146155 root = id [root ];
147156 }
148-
149- while (target != root ) {
150- final int next = id [target ];
151- id [target ] = root ;
152- target = next ;
153- }
154-
155157 return root ;
156158 }
157159
158- public int componentSize (final int p ) {
159- return sz [find (p )];
160- }
161-
162- public int components () {
163- return numComponents ;
164- }
165-
166- @ SuppressWarnings ("PMD.OnlyOneReturn" )
167- public int unify (final int p , final int q ) {
168- if (find (p ) == find (q )) {
169- return 0 ;
170- }
160+ public void unify (final int p , final int q ) {
171161 final int root1 = find (p );
172162 final int root2 = find (q );
173- if (sz [ root1 ] < sz [ root2 ] ) {
174- sz [root2 ] += sz [root1 ];
175- id [ root1 ] = root2 ;
176- sz [root1 ] = 0 ;
177- numComponents -- ;
178- return root2 ;
179- } else {
180- sz [ root1 ] += sz [root2 ];
181- id [root2 ] = root1 ;
182- sz [ root2 ] = 0 ;
163+ if (root1 != root2 ) {
164+ if ( sz [root1 ] < sz [root2 ]) {
165+ sz [ root2 ] += sz [ root1 ] ;
166+ id [root1 ] = root2 ;
167+ sz [ root1 ] = 0 ;
168+ } else {
169+ sz [ root1 ] += sz [ root2 ];
170+ id [root2 ] = root1 ;
171+ sz [root2 ] = 0 ;
172+ }
183173 numComponents --;
184- return root1 ;
185174 }
186175 }
187176 }
0 commit comments