132 lines
4.2 KiB
Kotlin

package aoc2023
import println
import readInput
/*
--- Day 25: Snowverload ---
https://adventofcode.com/2023/day/25
*/
fun main() {
val inlineTestInput = """
jqt: rhn xhk nvd
rsh: frs pzl lsr
xhk: hfx
cmg: qnr nvd lhk bvb
rhn: xhk bvb hfx
bvb: xhk hfx
pzl: lsr hfx nvd
qnr: nvd
ntq: jqt hfx bvb xhk
nvd: lhk
lsr: lhk
rzs: qnr cmg lsr rsh
frs: qnr lhk lsr
"""
data class Node(val id: String, val children: MutableSet<Node> = HashSet(), val orgNodes: MutableSet<Node> = HashSet()) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as Node
return id == other.id
}
override fun hashCode(): Int {
return id.hashCode()
}
override fun toString(): String {
return "Node(id='$id', children=${children.joinToString { it.id }})"
}
}
fun connectedSize(rootNode: Node): Int {
val visited = HashSet<Node>()
val queue = ArrayDeque<Node>()
queue.add(rootNode)
while (queue.isNotEmpty()) {
val n = queue.removeFirst()
visited.add(n)
n.children.forEach { if (!visited.contains(it)) queue.add(it) }
}
return visited.size
}
fun part1(input: List<String>): Int {
val nodeMap = HashMap<String, Node>()
for (i in input) {
val (from, to) = i.split(": ")
val tos = to.split(" ")
val fromNode = nodeMap.computeIfAbsent(from) { Node(from) }
val toNodes = tos.map { nodeMap.computeIfAbsent(it) { Node(it) } }
fromNode.children.addAll(toNodes)
toNodes.forEach { it.children.add(fromNode) }
}
nodeMap["vps"]!!.children.remove(nodeMap["pzc"])
nodeMap["pzc"]!!.children.remove(nodeMap["vps"])
nodeMap["xvk"]!!.children.remove(nodeMap["sgc"])
nodeMap["sgc"]!!.children.remove(nodeMap["xvk"])
nodeMap["dph"]!!.children.remove(nodeMap["cvx"])
nodeMap["cvx"]!!.children.remove(nodeMap["dph"])
val res = connectedSize(nodeMap["vps"]!!) * connectedSize(nodeMap["pzc"]!!)
// val edges = nodeMap.values.map { s -> s.children.map { t -> s to t } }.flatten()
//
// val nodes = nodeMap.values.toMutableList()
// while (nodes.size > 2) {
// val n1 = nodes[(Math.random() * nodes.size).toInt().coerceAtMost(nodes.lastIndex)]
// val n2 = n1.children.keys.toList()[(Math.random() * n1.children.size).toInt().coerceAtMost(n1.children.size - 1)]
// val superNode = Node(n1.id + "-" + n2.id)
// if (n1.orgNodes.isEmpty()) {
// superNode.orgNodes.add(Node(n1.id, children = HashMap(n1.children)))
// } else {
// superNode.orgNodes.addAll(n1.orgNodes)
// }
// if (n2.orgNodes.isEmpty()) {
// superNode.orgNodes.add(Node(n2.id, children = HashMap(n2.children)))
// } else {
// superNode.orgNodes.addAll(n2.orgNodes)
// }
// n1.children.filter { it.key != n2 }
// .forEach { }
// superNode.children.addAll(n1.children.filter { it != n2 })
// superNode.children.addAll(n2.children.filter { it != n1 })
//
// superNode.children.forEach {
// it.children.remove(n1)
// it.children.remove(n2)
// it.children.add(superNode)
// }
// nodes.remove(n1)
// nodes.remove(n2)
// nodes.add(superNode)
// }
return res
}
fun part2(input: List<String>): Int {
return 0
}
// test if implementation meets criteria from the description, like:
val testInput = inlineTestInput.trim().reader().readLines()
//val testInput = readInput("aoc2023/Day25_test")
//val testInputPart1Result = part1(testInput)
//println("Part 1 Test: $testInputPart1Result")
val testInputPart2Result = part2(testInput)
println("Part 2 Test: $testInputPart2Result")
//check(testInputPart1Result == 0)
check(testInputPart2Result == 0)
val input = readInput("aoc2023/Day25")
part1(input).println()
part2(input).println()
}