diff --git a/src/Day05.kt b/src/Day05.kt index 93c9d21..6da163c 100644 --- a/src/Day05.kt +++ b/src/Day05.kt @@ -5,6 +5,9 @@ class Day05( private val updates: List> companion object { + val UNVISITED = 0 + val OPEN = 1 + val DONE = 2 } init { @@ -17,26 +20,61 @@ class Day05( .map { line -> line.split("|").map(String::toInt).let { it[0] to it[1] } }.forEach { (before, after) -> - getOrPut(after) { mutableSetOf() }.add(before) + getOrPut(before) { mutableSetOf() }.add(after) } } this.updates = updates.lineSequence().map { line -> line.split(",").map(String::toInt).toList() }.toList() } + private fun printGraph() { + println("digraph G {") + + rules.forEach { u, vs -> + vs.forEach { v -> + println("\t$u -> $v") + } + } + + println("}") + } + override fun precompute() { // no-op } private fun isCorrect(update: List): Boolean = - update.withIndex().reversed().all { p -> - rules.getOrDefault(p.value, mutableSetOf()).all { preceding -> update.lastIndexOf(preceding) < p.index } + update.withIndex().all { p -> + rules + .getOrDefault(p.value, mutableSetOf()) + .all { succeeding -> update.indexOf(succeeding).let { it == -1 || it > p.index } } } override fun part1(): Int = updates.filter(::isCorrect).sumOf { it[it.size / 2] } - private fun fix(update: List): List = update + // Toposort + private fun fix(xs: Set): List { + val ordering = mutableListOf() + val state = mutableMapOf() - override fun part2(): Int = updates.filter { !isCorrect(it) }.map { fix(it) }.sumOf { it[it.size / 2] } + fun visit(u: Int) { + if (state.getOrDefault(u, UNVISITED) == DONE) { + return + } + check(state.getOrDefault(u, UNVISITED) != OPEN) { "We have found a loop ending in $u" } + + state[u] = OPEN + // ‹.intersect()›: Recursively search only the interesting successors + rules.getOrDefault(u, emptySet()).intersect(xs).forEach { visit(it) } + + state[u] = DONE + ordering.add(u) + } + xs.forEach { visit(it) } + + return ordering + } + + override fun part2(): Int = updates.filter { !isCorrect(it) }.map { fix(it.toSet()) }.sumOf { it[it.size / 2] } } fun main() {