Skip to content

Commit ae413a6

Browse files
committed
feat: day8 2025
1 parent a3c7df4 commit ae413a6

3 files changed

Lines changed: 207 additions & 5 deletions

File tree

src/main/kotlin/cz/glubo/adventofcode/utils/Utils.kt

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,53 @@ data class IVec2(
3232
infix fun tcDistance(other: IVec2) = abs(this.x - other.x) + abs(this.y - other.y)
3333
}
3434

35+
data class IVec3(
36+
val x: Int,
37+
val y: Int,
38+
val z: Int,
39+
) {
40+
operator fun plus(other: IVec3) =
41+
IVec3(
42+
this.x + other.x,
43+
this.y + other.y,
44+
this.z + other.z,
45+
)
46+
47+
operator fun minus(other: IVec3) =
48+
IVec3(
49+
this.x - other.x,
50+
this.y - other.y,
51+
this.z - other.z,
52+
)
53+
54+
operator fun times(scale: Int) =
55+
IVec3(
56+
scale * this.x,
57+
scale * this.y,
58+
scale * this.z,
59+
)
60+
61+
infix fun dot(other: IVec3) =
62+
this.x.toLong() * other.x +
63+
this.y.toLong() * other.y +
64+
this.z.toLong() * other.z
65+
66+
/**
67+
* Calculates the taxicab distance between this vector and the given vector.
68+
*
69+
* The taxicab distance is the sum of the absolute differences of the corresponding coordinates of the vectors.
70+
*
71+
* @param other The vector to calculate the taxicab distance to.
72+
* @return The taxicab distance between this vector and the given vector.
73+
*/
74+
infix fun tcDistance(other: IVec3) = abs(this.x - other.x) + abs(this.y - other.y) + abs(this.z - other.z)
75+
76+
infix fun squareDistance(other: IVec3): Long {
77+
val diff = this - other
78+
return diff dot diff
79+
}
80+
}
81+
3582
enum class FullDirection(
3683
val vector: IVec2,
3784
val char: Char,
Lines changed: 117 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,130 @@
11
package cz.glubo.adventofcode.y2025.day8
22

3+
import cz.glubo.adventofcode.utils.IVec3
34
import cz.glubo.adventofcode.utils.input.Input
45
import io.klogging.noCoLogger
6+
import kotlin.math.roundToLong
7+
import kotlin.math.sqrt
58

69
val logger = noCoLogger({}.javaClass.toString())
710

8-
suspend fun y2025day8part1(input: Input): Long {
11+
class UnionFind(
12+
size: Int,
13+
) {
14+
val parents = MutableList(size) { it }
15+
16+
fun findRoot(x: Int): Int {
17+
val parent = parents[x]
18+
return if (parents[parent] != parent) {
19+
findRoot(parent).also { parents[x] = it }
20+
} else {
21+
parent
22+
}
23+
}
24+
25+
fun markUnion(
26+
x: Int,
27+
y: Int,
28+
) {
29+
val rootX = findRoot(x)
30+
val rootY = findRoot(y)
31+
parents[rootX] = rootY
32+
}
33+
34+
fun sizes(): List<Int> =
35+
parents
36+
.groupBy { findRoot(it) }
37+
.map { (_, it) -> it.size }
38+
}
39+
40+
suspend fun y2025day8part1(
41+
input: Input,
42+
num: Int = 1000,
43+
): Long {
944
logger.info("year 2025 day 8 part 1")
10-
return 0
45+
val points = mutableListOf<IVec3>()
46+
input.lineFlow().collect { line ->
47+
val (x, y, z) =
48+
line
49+
.split(',')
50+
.map { it.toInt() }
51+
points.add(IVec3(x, y, z))
52+
}
53+
54+
data class Connection(
55+
val i: Int,
56+
val j: Int,
57+
val squareLength: Long,
58+
) {
59+
fun length() = sqrt(squareLength.toDouble()).roundToLong()
60+
}
61+
62+
val allConnections =
63+
points.indices.flatMap { i ->
64+
(i + 1..<points.size).map { j ->
65+
Connection(
66+
i,
67+
j,
68+
points[i] squareDistance points[j],
69+
)
70+
}
71+
}
72+
val chosenConnections =
73+
allConnections
74+
.sortedBy { it.squareLength }
75+
.take(num)
76+
val union = UnionFind(points.size)
77+
chosenConnections.forEach { conn ->
78+
union.markUnion(conn.i, conn.j)
79+
}
80+
81+
return union
82+
.sizes()
83+
.sortedByDescending { it }
84+
.take(3)
85+
.fold(1L) { acc, i -> acc * i }
1186
}
1287

1388
suspend fun y2025day8part2(input: Input): Long {
1489
logger.info("year 2025 day 8 part 2")
15-
return 0
90+
val points = mutableListOf<IVec3>()
91+
input.lineFlow().collect { line ->
92+
val (x, y, z) =
93+
line
94+
.split(',')
95+
.map { it.toInt() }
96+
points.add(IVec3(x, y, z))
97+
}
98+
99+
data class Connection(
100+
val i: Int,
101+
val j: Int,
102+
val squareLength: Long,
103+
) {
104+
fun length() = sqrt(squareLength.toDouble()).roundToLong()
105+
}
106+
107+
val allConnections =
108+
points.indices
109+
.flatMap { i ->
110+
(i + 1..<points.size).map { j ->
111+
Connection(
112+
i,
113+
j,
114+
points[i] squareDistance points[j],
115+
)
116+
}
117+
}.sortedBy { it.squareLength }
118+
val union = UnionFind(points.size)
119+
120+
var lastConnection: Connection
121+
var i = 0
122+
do {
123+
val conn = allConnections[i]
124+
union.markUnion(conn.i, conn.j)
125+
lastConnection = conn
126+
i++
127+
} while (union.sizes().size > 1 && allConnections.indices.contains((i)))
128+
129+
return points[lastConnection.i].x.toLong() * points[lastConnection.j].x.toLong()
16130
}

src/test/kotlin/cz/glubo/adventofcode/y2025/day8/Day8Test.kt

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,58 @@ class Day8Test :
1414
y2025day8part1(
1515
TestInput(
1616
"""
17+
162,817,812
18+
57,618,57
19+
906,360,560
20+
592,479,940
21+
352,342,300
22+
466,668,158
23+
542,29,236
24+
431,825,988
25+
739,650,466
26+
52,470,668
27+
216,146,977
28+
819,987,18
29+
117,168,530
30+
805,96,715
31+
346,949,466
32+
970,615,88
33+
941,993,340
34+
862,61,35
35+
984,92,344
36+
425,690,689
1737
""".trimIndent(),
1838
),
19-
) shouldBe 0
39+
10,
40+
) shouldBe 40
2041
}
2142

2243
"day8 example part 2 matches" {
2344
y2025day8part2(
2445
TestInput(
2546
"""
47+
162,817,812
48+
57,618,57
49+
906,360,560
50+
592,479,940
51+
352,342,300
52+
466,668,158
53+
542,29,236
54+
431,825,988
55+
739,650,466
56+
52,470,668
57+
216,146,977
58+
819,987,18
59+
117,168,530
60+
805,96,715
61+
346,949,466
62+
970,615,88
63+
941,993,340
64+
862,61,35
65+
984,92,344
66+
425,690,689
2667
""".trimIndent(),
2768
),
28-
) shouldBe 0
69+
) shouldBe 25272
2970
}
3071
})

0 commit comments

Comments
 (0)