diff --git a/input/2021/day12-sample1.txt b/input/2021/day12-sample1.txt new file mode 100644 index 0000000..6fd8c41 --- /dev/null +++ b/input/2021/day12-sample1.txt @@ -0,0 +1,7 @@ +start-A +start-b +A-c +A-b +b-d +A-end +b-end diff --git a/input/2021/day12-sample2.txt b/input/2021/day12-sample2.txt new file mode 100644 index 0000000..62cc714 --- /dev/null +++ b/input/2021/day12-sample2.txt @@ -0,0 +1,10 @@ +dc-end +HN-start +start-kj +dc-start +dc-HN +LN-dc +HN-end +kj-sa +kj-HN +kj-dc diff --git a/input/2021/day12-sample3.txt b/input/2021/day12-sample3.txt new file mode 100644 index 0000000..65f3833 --- /dev/null +++ b/input/2021/day12-sample3.txt @@ -0,0 +1,18 @@ +fs-end +he-DX +fs-he +start-DX +pj-DX +end-zg +zg-sl +zg-pj +pj-he +RW-he +fs-DX +pj-RW +zg-RW +start-pj +he-WI +zg-he +pj-fs +start-RW diff --git a/input/2021/day12.txt b/input/2021/day12.txt new file mode 100644 index 0000000..ad9b759 --- /dev/null +++ b/input/2021/day12.txt @@ -0,0 +1,22 @@ +xx-xh +vx-qc +cu-wf +ny-LO +cu-DR +start-xx +LO-vx +cu-LO +xx-cu +cu-ny +xh-start +qc-DR +vx-AP +end-LO +ny-DR +vx-end +DR-xx +start-DR +end-ny +ny-xx +xh-DR +cu-xh diff --git a/src/main/scala/de.qwertyuiop.aoc/2021/day12.scala b/src/main/scala/de.qwertyuiop.aoc/2021/day12.scala index 3c98a57..500f675 100644 --- a/src/main/scala/de.qwertyuiop.aoc/2021/day12.scala +++ b/src/main/scala/de.qwertyuiop.aoc/2021/day12.scala @@ -3,4 +3,24 @@ package de.qwertyuiop.aoc.`2021` import de.qwertyuiop.aoc.lib.* import cats.*, cats.implicits.given -def day12(using InputSource): Unit = ??? +def day12(using InputSource): Unit = + val edges = input(_.splitOnce("-").getOrElse(sys.error("Invalid input"))) + .flatMap((s,t) => List((s,t), (t,s))) + .groupMapReduce(_(0))(e => Set(e(1)))(_ | _) + + def countPaths(edges: Map[String, Set[String]], allowSmallDoubleVisit: Boolean): Int= + def rec(pathHead: String, visitedSmall: Set[String], canStillDoubleVisit: Boolean): Int= + val neighbours = edges(pathHead).filter(n => n != "start" && (canStillDoubleVisit || !visitedSmall.contains(n))) + neighbours.toVector.map(n => + if n == "end" then 1 + else if n.head.isLower then + rec(n, visitedSmall + n, !visitedSmall.contains(n) && canStillDoubleVisit) + else + rec(n, visitedSmall, canStillDoubleVisit) + ).sum + rec("start", Set("start"), allowSmallDoubleVisit) + + val allPaths = countPaths(edges, false) + val allPathsWithDoubleVisit = countPaths(edges, true) + println(s"Found ${allPaths} paths with single visits on small caves only") + println(s"Found ${allPathsWithDoubleVisit} paths with one double visit")