This commit is contained in:
Chris Hodges 2025-12-08 06:58:11 +01:00
parent 5fc0e8756a
commit 7a58627132

123
src/aoc2025/Day08.kt Normal file
View File

@ -0,0 +1,123 @@
package aoc2025
import println
import readInput
import splitInts
import kotlin.math.sqrt
/*
--- Day 8: Playground ---
https://adventofcode.com/2025/day/8
*/
fun main() {
val inlineTestInput = """
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
"""
fun dist(n1: IntArray, n2: IntArray) =
sqrt(((n1[0] - n2[0]).toFloat() * (n1[0] - n2[0]) + (n1[1] - n2[1]).toFloat() * (n1[1] - n2[1]) + (n1[2] - n2[2]).toFloat() * (n1[2] - n2[2])))
fun find(parent: IntArray, n: Int): Int {
if (parent[n] != n) {
parent[n] = find(parent, parent[n])
}
return parent[n]
}
fun union(parent: IntArray, n1: Int, n2: Int): Boolean {
val r1 = find(parent, n1)
val r2 = find(parent, n2)
if (r1 != r2) {
parent[r1] = r2
return true
}
return false
}
// priority queue would have been more efficient... who cares
fun createDistances(nodes: Array<IntArray>): Iterable<Pair<Pair<Int, Int>, Float>> {
val distances = ArrayList<Pair<Pair<Int, Int>, Float>>()
for (i1 in 0 until nodes.size) {
for (i2 in i1 + 1 until nodes.size) {
val d = dist(nodes[i1], nodes[i2])
distances.add((i1 to i2) to d)
}
}
distances.sortBy { it.second }
return distances
}
fun part1(input: List<String>, numConnections: Int): Long {
val nodes = input.map { it.splitInts(",").toIntArray() }.toTypedArray()
val distances = createDistances(nodes)
val n = nodes.size
var numCircuits = 0
val unionFindParentArray = IntArray(n) { it }
for (d in distances) {
val (n1, n2) = d.first
union(unionFindParentArray, n1, n2)
numCircuits++
if (numCircuits == numConnections) break
}
val circuitSizes = LongArray(n)
for (i in 0 until n) {
circuitSizes[find(unionFindParentArray, i)]++
}
return circuitSizes.sortedDescending().take(3).fold(1L) { acc, l -> acc * l }
}
fun part2(input: List<String>): Int {
val nodes = input.map { it.splitInts(",").toIntArray() }.toTypedArray()
val distances = createDistances(nodes)
val n = nodes.size
var numCircuits = 1
val unionFindParentArray = IntArray(n) { it }
for (d in distances) {
val (n1, n2) = d.first
if (union(unionFindParentArray, n1, n2)) {
numCircuits++
if (numCircuits == n) {
return nodes[n1][0] * nodes[n2][0]
}
}
}
return -1
}
// test if implementation meets criteria from the description, like:
val testInput = inlineTestInput.trim().reader().readLines()
//val testInput = readInput("aoc2025/Day08_test")
val testInputPart1Result = part1(testInput, 10)
println("Part 1 Test: $testInputPart1Result")
val testInputPart2Result = part2(testInput)
println("Part 2 Test: $testInputPart2Result")
check(testInputPart1Result == 40L)
check(testInputPart2Result == 25272)
val input = readInput("aoc2025/Day08")
part1(input, 1000).println()
part2(input).println()
}