diff --git a/src/main/kotlin/cz/glubo/adventofcode/Main.kt b/src/main/kotlin/cz/glubo/adventofcode/Main.kt index da94381..8db5a71 100644 --- a/src/main/kotlin/cz/glubo/adventofcode/Main.kt +++ b/src/main/kotlin/cz/glubo/adventofcode/Main.kt @@ -331,6 +331,8 @@ fun main(args: Array) { "2025day8p2" to InputToLongCommand { y2025day8part2(it) }, "2025day10p1" to InputToLongCommand { y2025day10part1(it) }, "2025day10p2" to InputToLongCommand { y2025day10part2(it) }, + "2024day25p1" to InputToLongCommand { y2024day25part1(it) }, + "2024day25p2" to InputToLongCommand { y2024day25part2(it) }, ) val cmd = CommandLine(MyHelpCommand()) diff --git a/src/main/kotlin/cz/glubo/adventofcode/utils/Utils.kt b/src/main/kotlin/cz/glubo/adventofcode/utils/Utils.kt index 7a463e8..e8cb2de 100644 --- a/src/main/kotlin/cz/glubo/adventofcode/utils/Utils.kt +++ b/src/main/kotlin/cz/glubo/adventofcode/utils/Utils.kt @@ -32,6 +32,53 @@ data class IVec2( infix fun tcDistance(other: IVec2) = abs(this.x - other.x) + abs(this.y - other.y) } +data class IVec3( + val x: Int, + val y: Int, + val z: Int, +) { + operator fun plus(other: IVec3) = + IVec3( + this.x + other.x, + this.y + other.y, + this.z + other.z, + ) + + operator fun minus(other: IVec3) = + IVec3( + this.x - other.x, + this.y - other.y, + this.z - other.z, + ) + + operator fun times(scale: Int) = + IVec3( + scale * this.x, + scale * this.y, + scale * this.z, + ) + + infix fun dot(other: IVec3) = + this.x.toLong() * other.x + + this.y.toLong() * other.y + + this.z.toLong() * other.z + + /** + * Calculates the taxicab distance between this vector and the given vector. + * + * The taxicab distance is the sum of the absolute differences of the corresponding coordinates of the vectors. + * + * @param other The vector to calculate the taxicab distance to. + * @return The taxicab distance between this vector and the given vector. + */ + infix fun tcDistance(other: IVec3) = abs(this.x - other.x) + abs(this.y - other.y) + abs(this.z - other.z) + + infix fun squareDistance(other: IVec3): Long { + val diff = this - other + return diff dot diff + } +} + enum class FullDirection( val vector: IVec2, val char: Char, diff --git a/src/main/kotlin/cz/glubo/adventofcode/y2025/day8/Day8.kt b/src/main/kotlin/cz/glubo/adventofcode/y2025/day8/Day8.kt index 8b51147..5535694 100644 --- a/src/main/kotlin/cz/glubo/adventofcode/y2025/day8/Day8.kt +++ b/src/main/kotlin/cz/glubo/adventofcode/y2025/day8/Day8.kt @@ -1,16 +1,130 @@ package cz.glubo.adventofcode.y2025.day8 +import cz.glubo.adventofcode.utils.IVec3 import cz.glubo.adventofcode.utils.input.Input import io.klogging.noCoLogger +import kotlin.math.roundToLong +import kotlin.math.sqrt val logger = noCoLogger({}.javaClass.toString()) -suspend fun y2025day8part1(input: Input): Long { +class UnionFind( + size: Int, +) { + val parents = MutableList(size) { it } + + fun findRoot(x: Int): Int { + val parent = parents[x] + return if (parents[parent] != parent) { + findRoot(parent).also { parents[x] = it } + } else { + parent + } + } + + fun markUnion( + x: Int, + y: Int, + ) { + val rootX = findRoot(x) + val rootY = findRoot(y) + parents[rootX] = rootY + } + + fun sizes(): List = + parents + .groupBy { findRoot(it) } + .map { (_, it) -> it.size } +} + +suspend fun y2025day8part1( + input: Input, + num: Int = 1000, +): Long { logger.info("year 2025 day 8 part 1") - return 0 + val points = mutableListOf() + input.lineFlow().collect { line -> + val (x, y, z) = + line + .split(',') + .map { it.toInt() } + points.add(IVec3(x, y, z)) + } + + data class Connection( + val i: Int, + val j: Int, + val squareLength: Long, + ) { + fun length() = sqrt(squareLength.toDouble()).roundToLong() + } + + val allConnections = + points.indices.flatMap { i -> + (i + 1.. + Connection( + i, + j, + points[i] squareDistance points[j], + ) + } + } + val chosenConnections = + allConnections + .sortedBy { it.squareLength } + .take(num) + val union = UnionFind(points.size) + chosenConnections.forEach { conn -> + union.markUnion(conn.i, conn.j) + } + + return union + .sizes() + .sortedByDescending { it } + .take(3) + .fold(1L) { acc, i -> acc * i } } suspend fun y2025day8part2(input: Input): Long { logger.info("year 2025 day 8 part 2") - return 0 + val points = mutableListOf() + input.lineFlow().collect { line -> + val (x, y, z) = + line + .split(',') + .map { it.toInt() } + points.add(IVec3(x, y, z)) + } + + data class Connection( + val i: Int, + val j: Int, + val squareLength: Long, + ) { + fun length() = sqrt(squareLength.toDouble()).roundToLong() + } + + val allConnections = + points.indices + .flatMap { i -> + (i + 1.. + Connection( + i, + j, + points[i] squareDistance points[j], + ) + } + }.sortedBy { it.squareLength } + val union = UnionFind(points.size) + + var lastConnection: Connection + var i = 0 + do { + val conn = allConnections[i] + union.markUnion(conn.i, conn.j) + lastConnection = conn + i++ + } while (union.sizes().size > 1 && allConnections.indices.contains((i))) + + return points[lastConnection.i].x.toLong() * points[lastConnection.j].x.toLong() } diff --git a/src/test/kotlin/cz/glubo/adventofcode/y2025/day8/Day8Test.kt b/src/test/kotlin/cz/glubo/adventofcode/y2025/day8/Day8Test.kt index ca2fd33..6122e33 100644 --- a/src/test/kotlin/cz/glubo/adventofcode/y2025/day8/Day8Test.kt +++ b/src/test/kotlin/cz/glubo/adventofcode/y2025/day8/Day8Test.kt @@ -14,17 +14,58 @@ class Day8Test : y2025day8part1( TestInput( """ + 162,817,812 + 57,618,57 + 906,360,560 + 592,479,940 + 352,342,300 + 466,668,158 + 542,29,236 + 431,825,988 + 739,650,466 + 52,470,668 + 216,146,977 + 819,987,18 + 117,168,530 + 805,96,715 + 346,949,466 + 970,615,88 + 941,993,340 + 862,61,35 + 984,92,344 + 425,690,689 """.trimIndent(), ), - ) shouldBe 0 + 10, + ) shouldBe 40 } "day8 example part 2 matches" { y2025day8part2( TestInput( """ + 162,817,812 + 57,618,57 + 906,360,560 + 592,479,940 + 352,342,300 + 466,668,158 + 542,29,236 + 431,825,988 + 739,650,466 + 52,470,668 + 216,146,977 + 819,987,18 + 117,168,530 + 805,96,715 + 346,949,466 + 970,615,88 + 941,993,340 + 862,61,35 + 984,92,344 + 425,690,689 """.trimIndent(), ), - ) shouldBe 0 + ) shouldBe 25272 } })