day(05): solve part 2
Signed-off-by: Matej Focko <me@mfocko.xyz>
This commit is contained in:
parent
2632bc7a58
commit
ab88740e69
1 changed files with 43 additions and 5 deletions
48
src/Day05.kt
48
src/Day05.kt
|
@ -5,6 +5,9 @@ class Day05(
|
|||
private val updates: List<List<Int>>
|
||||
|
||||
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<Int>): 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<Int>): List<Int> = update
|
||||
// Toposort
|
||||
private fun fix(xs: Set<Int>): List<Int> {
|
||||
val ordering = mutableListOf<Int>()
|
||||
val state = mutableMapOf<Int, Int>()
|
||||
|
||||
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() {
|
||||
|
|
Loading…
Reference in a new issue