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 = HashSet(), val orgNodes: MutableSet = 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() val queue = ArrayDeque() 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): Int { val nodeMap = HashMap() 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): 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() }