day(05): solve part 2

Signed-off-by: Matej Focko <me@mfocko.xyz>
This commit is contained in:
Matej Focko 2024-12-05 15:10:10 +01:00
parent 2632bc7a58
commit ab88740e69
Signed by: mfocko
SSH key fingerprint: SHA256:icm0fIOSJUpy5+1x23sfr+hLtF9UhY8VpMC7H4WFJP8

View file

@ -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() {