Das Geböller an Silvester ist ja schon schlimm genug, aber noch schlimmer finde ich die, die meinen schon ein paar Tage davor schon Krach machen zu müssen.
A bit late to the party, but here's my solution.
I don't know, if you even need to search for the smallest integer vector in the same direction in part 2, but I did it anyway.
I finally got around to doing day 7. I try the brute force method (takes several seconds), but I'm particularly proud of my sequence generator for operation permutations.
The Collection#rotate method is in the file Utils.kt, which can be found in my repo.
I have a conjecture though, that any looping solution, obtained by adding one obstacle, would eventually lead to a rectangular loop. That may lead to a non brute-force solution. It's quite hard to prove rigorously though. (Maybe proving, that the loop has to be convex, which is an equivalent statement here, is easier? You can also find matrix representations of the guard's state changes, if that helps.)
Maybe some of the more mathematically inclined people here can try proving or disproving that.
That was an easy one, once you define a comparator function. (At least when you have a sorting function in your standard-library.)
The biggest part was the parsing. lol
import kotlin.text.Regex
fun main() {
fun part1(input: List<String>): Int = parseInput(input).sumOf { if (it.isCorrectlyOrdered()) it[it.size / 2].pageNumber else 0 }
fun part2(input: List<String>): Int = parseInput(input).sumOf { if (!it.isCorrectlyOrdered()) it.sorted()[it.size / 2].pageNumber else 0 }
val testInput = readInput("Day05_test")
check(part1(testInput) == 143)
check(part2(testInput) == 123)
val input = readInput("Day05")
part1(input).println()
part2(input).println()
}
fun parseInput(input: List<String>): List<List<Page>> {
val (orderRulesStrings, pageSequencesStrings) = input.filter { it.isNotEmpty() }.partition { Regex("""\d+\|\d+""").matches(it) }
val orderRules = orderRulesStrings.map { with(it.split('|')) { this[0].toInt() to this[1].toInt() } }
val orderRulesX = orderRules.map { it.first }.toSet()
val pages = orderRulesX.map { pageNumber ->
val orderClasses = orderRules.filter { it.first == pageNumber }.map { it.second }
Page(pageNumber, orderClasses)
}.associateBy { it.pageNumber }
val pageSequences = pageSequencesStrings.map { sequenceString ->
sequenceString.split(',').map { pages[it.toInt()] ?: Page(it.toInt(), emptyList()) }
}
return pageSequences
}
/*
* An order class is an equivalence class for every page with the same page to be printed before.
*/
data class Page(val pageNumber: Int, val orderClasses: List<Int>): Comparable<Page> {
override fun compareTo(other: Page): Int =
if (other.pageNumber in orderClasses) -1
else if (pageNumber in other.orderClasses) 1
else 0
}
fun List<Page>.isCorrectlyOrdered(): Boolean = this == this.sorted()
Free lobotomy?