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>>
|
private val updates: List<List<Int>>
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
val UNVISITED = 0
|
||||||
|
val OPEN = 1
|
||||||
|
val DONE = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -17,26 +20,61 @@ class Day05(
|
||||||
.map { line ->
|
.map { line ->
|
||||||
line.split("|").map(String::toInt).let { it[0] to it[1] }
|
line.split("|").map(String::toInt).let { it[0] to it[1] }
|
||||||
}.forEach { (before, after) ->
|
}.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()
|
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() {
|
override fun precompute() {
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isCorrect(update: List<Int>): Boolean =
|
private fun isCorrect(update: List<Int>): Boolean =
|
||||||
update.withIndex().reversed().all { p ->
|
update.withIndex().all { p ->
|
||||||
rules.getOrDefault(p.value, mutableSetOf()).all { preceding -> update.lastIndexOf(preceding) < p.index }
|
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] }
|
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() {
|
fun main() {
|
||||||
|
|
Loading…
Reference in a new issue