I don't have a lot of time right now to work on these puzzles, so I was able to knock out Part A pretty easily, and my solution is similar to yours, but I'm just keeping my "ordering rules" in a list rather than a map. The Kotlin streams/functional interface makes it easy to find all the matching items from the list. I haven't had time to figure out Part B yet. I'm hoping I'll have time this weekend to get caught up, but we also have a bunch of things going on. I'm not sure I entirely followed how your solution works, so I'll see if I end up with something similar...
I don't have a lot of time right now to work on these puzzles, so I was able to knock out Part A pretty easily, and my solution is similar to yours, but I'm just keeping my "ordering rules" in a list rather than a map. The Kotlin streams/functional interface makes it easy to find all the matching items from the list.
I haven't had time to figure out Part B yet. I'm hoping I'll have time this weekend to get caught up, but we also have a bunch of things going on. I'm not sure I entirely followed how your solution works, so I'll see if I end up with something similar...
Day 5 was easier than day 4!
Part 1:
fun calc(input: List): Int {
val rules = input[0].split("
").groupBy({ it.split("|")[0] }) { it.substringAfter("|") }
val updates = input[1].split("
").map { it.split(",") }
return updates.filter { isValid(rules, it) }.sumOf { it[it.size/2].toInt() }
}
private fun isValid(rules: Map, update: List): Boolean =
update.map { s -> update.dropWhile { it != s } }.dropLast(1).all { l -> l.drop(1).all { rules[l.first()]?.contains(it) == true } }
Part 2:
fun calc(input: List): Int {
val rules = input[0].split("
").groupBy({ it.split("|")[0] }) { it.substringAfter("|") }
val incorrect = input[1].split("
").map { it.split(",") }.filter { !isValid(rules, it) }
val sorted = incorrect.map { it.sortedWith { a, b ->
if (rules[a]?.contains(b) == true) 1 else if (rules[b]?.contains(a) == true) -1 else 0 } }
return sorted.sumOf { it[it.size/2].toInt() }
}
private fun isValid(rules: Map, update: List): Boolean =
update.map { s -> update.dropWhile { it != s } }.dropLast(1)
.all { l -> l.drop(1).all { rules[l.first()]?.contains(it) == true } }
And as one-liners:
Part 1:
fun calc(input: List): Int = input[1].split("
").map { it.split(",") }
.filter { it.map { s -> it.dropWhile { it != s } }.dropLast(1)
.all { l -> l.drop(1).all { input[0].split("
").groupBy({ it.split("|")[0] })
{ it.substringAfter("|") }[l.first()]?.contains(it) == true } } }.sumOf { it[it.size/2].toInt() }
Part 2:
fun calc(input: List): Int =
(input[0].split("
").groupBy({ it.split("|")[0] }) { it.substringAfter("|") } to
input[1].split("
").map { it.split(",") }).let { p -> p.second.filter { !it.map {
s -> it.dropWhile { it != s } }.dropLast(1).all { l -> l.drop(1).all {
p.first[l.first()]?.contains(it) == true } } }.map {
it.sortedWith { a, b -> if (p.first[a]?.contains(b) == true) 1
else if (p.first[b]?.contains(a) == true) -1 else 0 } }
}.sumOf { it[it.size/2].toInt() }