diff --git a/src/aoc2024/Day23.kt b/src/aoc2024/Day23.kt new file mode 100644 index 0000000..2dfff82 --- /dev/null +++ b/src/aoc2024/Day23.kt @@ -0,0 +1,111 @@ +package aoc2024 + +import println +import readInput + +/* +--- Day 23: LAN Party --- +https://adventofcode.com/2024/day/23 +*/ +fun main() { + + val inlineTestInput = """ +kh-tc +qp-kh +de-cg +ka-co +yn-aq +qp-ub +cg-tb +vc-aq +tb-ka +wh-tc +yn-cg +kh-ub +ta-co +de-co +tc-td +tb-wq +wh-td +ta-ka +td-qp +aq-cg +wq-ub +ub-vc +de-ta +wq-aq +wq-vc +wh-yn +ka-de +kh-ta +co-tc +wh-qp +tb-vc +td-yn +""" + + fun part1(input: List): Int { + val nodes = HashMap>() + for (i in input) { + val (n1, n2) = i.split("-") + val e1 = nodes.getOrPut(n1) { HashSet() } + val e2 = nodes.getOrPut(n2) { HashSet() } + e1.add(n2) + e2.add(n1) + } + val threesomes = nodes + .flatMap { + it.value.flatMap { i1 -> + it.value.filter { it != i1 }.mapNotNull { i2 -> + if (nodes[i1]!!.contains(it.key) && nodes[i2]!!.contains(it.key) && nodes[i1]!!.contains(i2)) sortedSetOf(it.key, i1, i2) else null + } + } + }.map { it.joinToString("-", prefix = "-") }.distinct() + + return threesomes.count { it.contains("-t") } + } + + fun bronKerbosch(nodes: Map>, r: Set, p: Set, x: MutableSet): Set { + if (p.isEmpty() && x.isEmpty()) { + return r + } + var maxClique = emptySet() + val ptmp = p.toMutableSet() + for (v in p) { + val res = bronKerbosch(nodes, r.plus(v), ptmp.intersect(nodes[v]!!), x.intersect(nodes[v]!!).toMutableSet()) + if (res.size > maxClique.size) { + maxClique = res + } + ptmp.remove(v) + x.add(v) + } + return maxClique + } + + fun part2(input: List): String { + val nodes = HashMap>() + for (i in input) { + val (n1, n2) = i.split("-") + val e1 = nodes.getOrPut(n1) { HashSet() } + val e2 = nodes.getOrPut(n2) { HashSet() } + e1.add(n2) + e2.add(n1) + } + val largestSet = bronKerbosch(nodes, emptySet(), nodes.keys, mutableSetOf()) + return largestSet.asSequence().sorted().joinToString(",") + } + + // test if implementation meets criteria from the description, like: + val testInput = inlineTestInput.trim().reader().readLines() + //val testInput = readInput("aoc2024/Day23_test") + val testInputPart1Result = part1(testInput) + println("Part 1 Test: $testInputPart1Result") + val testInputPart2Result = part2(testInput) + println("Part 2 Test: $testInputPart2Result") + check(testInputPart1Result == 7) + check(testInputPart2Result == "co,de,ka,ta") + + val input = readInput("aoc2024/Day23") + part1(input).println() + part2(input).println() +}