diff --git a/src/main/scala/eu/sim642/adventofcode2024/Day23.scala b/src/main/scala/eu/sim642/adventofcode2024/Day23.scala index fd7d6bdd..129518be 100644 --- a/src/main/scala/eu/sim642/adventofcode2024/Day23.scala +++ b/src/main/scala/eu/sim642/adventofcode2024/Day23.scala @@ -16,6 +16,44 @@ object Day23 { def count3CliquesT(edges: Set[Edge]): Int = find3Cliques(edges).count(_.exists(_.startsWith("t"))) + // copied from 2018 day 23 + // TODO: move to library + def maximumClique(neighbors: Map[Computer, Set[Computer]]): Set[Computer] = { + var best: Set[Computer] = Set.empty + + def bronKerbosh(r: Set[Computer], p: Set[Computer], x: Set[Computer]): Unit = { + if (p.isEmpty && x.isEmpty) { + //println(r) + if (r.size > best.size) + best = r + } + else { + //val u = p.headOption.getOrElse(x.head) + val u = (p ++ x).maxBy(neighbors(_).size) // pivot on highest degree + var p2 = p + var x2 = x + for (v <- p -- neighbors(u)) { + bronKerbosh(r + v, p2 intersect neighbors(v), x2 intersect neighbors(v)) + p2 -= v + x2 += v + } + } + } + + bronKerbosh(Set.empty, neighbors.keySet, Set.empty) + best + } + + def maximumClique(edges: Set[Edge]): Set[Computer] = { + val neighbors = (edges ++ edges.map(_.swap)).groupMap(_._1)(_._2) + maximumClique(neighbors) + } + + def lanPartyPassword(edges: Set[Edge]): String = { + val clique = maximumClique(edges) + clique.toSeq.sorted.mkString(",") + } + def parseEdge(s: String): Edge = s match { case s"$from-$to" => (from, to) } @@ -26,6 +64,7 @@ object Day23 { def main(args: Array[String]): Unit = { println(count3CliquesT(parseEdges(input))) + println(lanPartyPassword(parseEdges(input))) // part 1: 2366 - too high (used contains 't' instead of startsWith 't') } diff --git a/src/test/scala/eu/sim642/adventofcode2024/Day23Test.scala b/src/test/scala/eu/sim642/adventofcode2024/Day23Test.scala index aba27855..e58c66b1 100644 --- a/src/test/scala/eu/sim642/adventofcode2024/Day23Test.scala +++ b/src/test/scala/eu/sim642/adventofcode2024/Day23Test.scala @@ -46,4 +46,12 @@ class Day23Test extends AnyFunSuite { test("Part 1 input answer") { assert(count3CliquesT(parseEdges(input)) == 1437) } + + test("Part 2 examples") { + assert(lanPartyPassword(parseEdges(exampleInput)) == "co,de,ka,ta") + } + + test("Part 2 input answer") { + assert(lanPartyPassword(parseEdges(input)) == "da,do,gx,ly,mb,ns,nt,pz,sc,si,tp,ul,vl") + } }