Skip to content

Commit 37e0529

Browse files
committed
AoC 2025 Day 8 - java
1 parent da2b7b4 commit 37e0529

File tree

3 files changed

+213
-19
lines changed

3 files changed

+213
-19
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
1010
| ---| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
1111
| python3 | [](src/main/python/AoC2025_01.py) | [](src/main/python/AoC2025_02.py) | [](src/main/python/AoC2025_03.py) | [](src/main/python/AoC2025_04.py) | [](src/main/python/AoC2025_05.py) | [](src/main/python/AoC2025_06.py) | [](src/main/python/AoC2025_07.py) | [](src/main/python/AoC2025_08.py) | | | | |
12-
| java | [](src/main/java/AoC2025_01.java) | [](src/main/java/AoC2025_02.java) | [](src/main/java/AoC2025_03.java) | [](src/main/java/AoC2025_04.java) | [](src/main/java/AoC2025_05.java) | [](src/main/java/AoC2025_06.java) | [](src/main/java/AoC2025_07.java) | | | | | |
12+
| java | [](src/main/java/AoC2025_01.java) | [](src/main/java/AoC2025_02.java) | [](src/main/java/AoC2025_03.java) | [](src/main/java/AoC2025_04.java) | [](src/main/java/AoC2025_05.java) | [](src/main/java/AoC2025_06.java) | [](src/main/java/AoC2025_07.java) | [](src/main/java/AoC2025_08.java) | | | | |
1313
| bash | [](src/main/bash/AoC2025_01.sh) | [](src/main/bash/AoC2025_02.sh) | [](src/main/bash/AoC2025_03.sh) | [](src/main/bash/AoC2025_04.sh) | [](src/main/bash/AoC2025_05.sh) | [](src/main/bash/AoC2025_06.sh) | [](src/main/bash/AoC2025_07.sh) | | | | | |
1414
<!-- @END:ImplementationsTable:2025@ -->
1515

src/main/java/AoC2025_08.java

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
import static com.github.pareronia.aoc.IntegerSequence.Range.range;
2+
3+
import static java.util.Comparator.comparing;
4+
import static java.util.Comparator.reverseOrder;
5+
import static java.util.stream.Collectors.toMap;
6+
7+
import com.github.pareronia.aoc.StringOps;
8+
import com.github.pareronia.aoc.geometry3d.Position3D;
9+
import com.github.pareronia.aoc.solution.SolutionBase;
10+
11+
import java.util.ArrayList;
12+
import java.util.Collections;
13+
import java.util.List;
14+
15+
@SuppressWarnings({"PMD.ClassNamingConventions", "PMD.NoPackage"})
16+
public final class AoC2025_08 extends SolutionBase<AoC2025_08.Input, Long, Long> {
17+
18+
private AoC2025_08(final boolean debug) {
19+
super(debug);
20+
}
21+
22+
public static AoC2025_08 create() {
23+
return new AoC2025_08(false);
24+
}
25+
26+
public static AoC2025_08 createDebug() {
27+
return new AoC2025_08(true);
28+
}
29+
30+
@Override
31+
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+
})
42+
.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));
50+
return new Input(boxes, pairs);
51+
}
52+
53+
private long solve1(final Input input, final int size) {
54+
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)
63+
.reduce((acc, sz) -> acc * sz)
64+
.get();
65+
}
66+
67+
@Override
68+
public Long solvePart1(final Input input) {
69+
return this.solve1(input, 1000);
70+
}
71+
72+
@Override
73+
public Long solvePart2(final Input input) {
74+
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");
83+
}
84+
85+
@Override
86+
protected void samples() {
87+
final AoC2025_08 test = createDebug();
88+
final Input input = test.parseInput(StringOps.splitLines(TEST));
89+
assert test.solve1(input, 10) == 40;
90+
assert test.solvePart2(input) == 25_272;
91+
}
92+
93+
public static void main(final String[] args) throws Exception {
94+
create().run();
95+
}
96+
97+
private static final String TEST =
98+
"""
99+
162,817,812
100+
57,618,57
101+
906,360,560
102+
592,479,940
103+
352,342,300
104+
466,668,158
105+
542,29,236
106+
431,825,988
107+
739,650,466
108+
52,470,668
109+
216,146,977
110+
819,987,18
111+
117,168,530
112+
805,96,715
113+
346,949,466
114+
970,615,88
115+
941,993,340
116+
862,61,35
117+
984,92,344
118+
425,690,689
119+
""";
120+
121+
record Pair(int first, int second, long distance) {}
122+
123+
record Input(List<Position3D> boxes, List<Pair> pairs) {}
124+
125+
private static class DSU {
126+
127+
private final int[] sz;
128+
private final int[] id;
129+
private int numComponents;
130+
131+
public DSU(final int size) {
132+
this.numComponents = size;
133+
sz = new int[size];
134+
id = new int[size];
135+
136+
for (int i = 0; i < size; i++) {
137+
id[i] = i;
138+
sz[i] = 1;
139+
}
140+
}
141+
142+
public int find(final int p) {
143+
int target = p;
144+
int root = target;
145+
while (root != id[root]) {
146+
root = id[root];
147+
}
148+
149+
while (target != root) {
150+
final int next = id[target];
151+
id[target] = root;
152+
target = next;
153+
}
154+
155+
return root;
156+
}
157+
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+
}
171+
final int root1 = find(p);
172+
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;
183+
numComponents--;
184+
return root1;
185+
}
186+
}
187+
}
188+
}

src/main/java/com/github/pareronia/aoc/geometry3d/Position3D.java

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,47 +7,53 @@ public class Position3D extends Point3D {
77
public Position3D(final int x, final int y, final int z) {
88
super(x, y, z);
99
}
10-
10+
1111
public static Position3D of(final int x, final int y, final int z) {
1212
return new Position3D(x, y, z);
1313
}
14-
14+
1515
public Position3D translate(final Vector3D vector) {
1616
return translate(vector, 1);
1717
}
18-
18+
1919
public Position3D translate(final Vector3D vector, final int amplitude) {
2020
return new Position3D(
2121
this.getX() + amplitude * vector.getX(),
2222
this.getY() + amplitude * vector.getY(),
2323
this.getZ() + amplitude * vector.getZ());
2424
}
25-
25+
2626
public double distance(final Position3D other) {
27-
return Math.sqrt(
28-
(other.getX() - this.getX()) * (other.getX() - this.getX()) +
29-
(other.getY() - this.getY()) * (other.getY() - this.getY()) +
30-
(other.getZ() - this.getZ()) * (other.getZ() - this.getZ())
31-
);
27+
return Math.sqrt(this.squaredDistance(other));
3228
}
33-
29+
30+
public long squaredDistance(final Position3D other) {
31+
final long dx = other.getX() - this.getX();
32+
final long dy = other.getY() - this.getY();
33+
final long dz = other.getZ() - this.getZ();
34+
return dx * dx + dy * dy + dz * dz;
35+
}
36+
3437
public Integer manhattanDistance(final Position3D from) {
3538
return Math.abs(this.getX() - from.getX())
3639
+ Math.abs(this.getY() - from.getY())
3740
+ Math.abs(this.getZ() - from.getZ());
3841
}
39-
42+
4043
public Stream<Position3D> capitalNeighbours() {
41-
return Direction3D.CAPITAL.stream()
42-
.map(Direction3D::getValue)
43-
.map(this::translate);
44+
return Direction3D.CAPITAL.stream().map(Direction3D::getValue).map(this::translate);
4445
}
45-
46+
4647
@Override
4748
public String toString() {
48-
final StringBuilder builder = new StringBuilder();
49-
builder.append("Position3D(x=").append(getX()).append(", y=")
50-
.append(getY()).append(", z=").append(getZ()).append(")");
49+
final StringBuilder builder = new StringBuilder(50);
50+
builder.append("Position3D(x=")
51+
.append(getX())
52+
.append(", y=")
53+
.append(getY())
54+
.append(", z=")
55+
.append(getZ())
56+
.append(')');
5157
return builder.toString();
5258
}
5359
}

0 commit comments

Comments
 (0)