aboutsummaryrefslogtreecommitdiff
path: root/aoc-2021-kotlin/src/Day12.kt
diff options
context:
space:
mode:
authortchojnacki <tomaszchojnacki2001@gmail.com>2022-08-11 19:24:23 +0200
committertchojnacki <tomaszchojnacki2001@gmail.com>2022-08-11 19:24:23 +0200
commit0f1e145b80813ae2331b7dac5ace0c589654ad2a (patch)
tree25483b8239436dd5aed2fee8811caf0ba893c0bb /aoc-2021-kotlin/src/Day12.kt
parent85fb0396bed6a2129b12392941103924b1ab55be (diff)
downloadgleam_aoc2020-0f1e145b80813ae2331b7dac5ace0c589654ad2a.tar.gz
gleam_aoc2020-0f1e145b80813ae2331b7dac5ace0c589654ad2a.zip
Move subproject to avoid IntelliJ module name issues
Diffstat (limited to 'aoc-2021-kotlin/src/Day12.kt')
-rw-r--r--aoc-2021-kotlin/src/Day12.kt72
1 files changed, 72 insertions, 0 deletions
diff --git a/aoc-2021-kotlin/src/Day12.kt b/aoc-2021-kotlin/src/Day12.kt
new file mode 100644
index 0000000..d3368da
--- /dev/null
+++ b/aoc-2021-kotlin/src/Day12.kt
@@ -0,0 +1,72 @@
+object Day12 {
+ private class CaveGraph {
+ companion object {
+ fun fromLines(input: List<String>): CaveGraph =
+ CaveGraph().apply { input.forEach { addConnection(it) } }
+ }
+
+ private val adjacencyList = mutableMapOf<Node, Set<Node>>()
+
+ private fun addConnection(connectionString: String) {
+ val (from, to) = connectionString.split("-").map(Node::fromString)
+
+ adjacencyList.merge(from, setOf(to), Set<Node>::union)
+ adjacencyList.merge(to, setOf(from), Set<Node>::union)
+ }
+
+ fun countPaths(canUseDoubleTraversal: Boolean = false): Int =
+ traverse(Node.Start, setOf(), !canUseDoubleTraversal)
+
+ private fun traverse(from: Node, visitedBefore: Set<Node>, usedUpDoubleTraverse: Boolean): Int {
+ return adjacencyList[from]!!.sumOf {
+ when (it) {
+ is Node.Start -> 0
+ is Node.End -> 1
+ is Node.Big -> traverse(it, visitedBefore + from, usedUpDoubleTraverse)
+ is Node.Small -> {
+ if (!visitedBefore.contains(it)) {
+ traverse(it, visitedBefore + from, usedUpDoubleTraverse)
+ } else if (!usedUpDoubleTraverse) {
+ traverse(it, visitedBefore + from, true)
+ } else {
+ 0
+ }
+ }
+ }
+ }
+ }
+
+ private sealed class Node {
+ companion object {
+ fun fromString(text: String): Node = when (text) {
+ "start" -> Start
+ "end" -> End
+ else -> if (text == text.uppercase()) {
+ Big(text)
+ } else {
+ Small(text)
+ }
+ }
+ }
+
+ object Start : Node()
+ object End : Node()
+ data class Small(private val identifier: String) : Node()
+ data class Big(private val identifier: String) : Node()
+ }
+ }
+
+ fun bothParts(input: List<String>) = CaveGraph.fromLines(input).let { it.countPaths() to it.countPaths(true) }
+}
+
+fun main() {
+ val testInput = readInputAsLines("Day12_test")
+ val testOutput = Day12.bothParts(testInput)
+ check(testOutput.first == 226)
+ check(testOutput.second == 3509)
+
+ val input = readInputAsLines("Day12")
+ val output = Day12.bothParts(input)
+ println(output.first)
+ println(output.second)
+}