V tento den mi chvíli (no, trochu déle) trvalo, než jsem vůbec pochopil zadaní první části, kterou jsem pak zvládl docela v pohodě. Ale pro část B jsem si již zašel pro radu na Kotlin Slack, kde trik spočíval v tom, že již po cca 100 iteracích se pattern usadí a přírůstky rostlin začnou být konstantní, což nám umožní všechny zbývající iterace vynechat úplně a výsledek jednoduše dopočítat.
import com.svetylkovo.rojo.Rojo import java.io.File val rulesMatcher = Rojo.matcher("(.+?) => (.+?)") class Replanter(initial: List<Int>, val rules: Map<List<Int>, Int>) { private var pots = initial.toMutableList() private var originIndexOffset = 0 init { ensureBothEmptyEnds() } fun nextStep() { pots.toList() .asSequence() .windowed(5, 1) .forEachIndexed { index, it -> val nextPotState = rules[it] pots[index + 2] = nextPotState ?: 0 } ensureBothEmptyEnds() } private fun ensureBothEmptyEnds(emptyEndsSize: Int = 3) { val leftEmpty = pots.takeWhile { it == 0 }.count() val rightEmpty = pots.takeLastWhile { it == 0 }.count() val leftToAppend = emptyEndsSize - leftEmpty val rightToAppend = emptyEndsSize - rightEmpty if (leftToAppend > 0) { originIndexOffset += leftToAppend pots.addAll(0, List(leftToAppend) { 0 }) } if (rightToAppend > 0) { pots.addAll(List(rightToAppend) { 0 }) } } fun stateAsString() = pots.joinToString("") { if (it == 1) "#" else "." } fun sumPotWithPlantNumbers(): Long = pots.asSequence() .mapIndexed { index, value -> (index - originIndexOffset) * value } .sum() .toLong() } fun String.toPlantStatesList() = map { if (it == '#') 1 else 0 } fun main() { val input = File("input12.txt").readText() val initial = "##...#......##......#.####.##.#..#..####.#.######.##..#.####...##....#.#.####.####.#..#.######.##...".toPlantStatesList() val rules = rulesMatcher.asMap(input) .mapKeys { it.key.toPlantStatesList() } .mapValues { it.value.toPlantStatesList().first() } //A val replanterA = Replanter(initial, rules) repeat(20) { replanterA.nextStep() } println(replanterA.sumPotWithPlantNumbers()) //B println("Computing part B") val replanterB = Replanter(initial, rules) //let's get to the last point before it settles repeat(98) { replanterB.nextStep() } val diffSettlesTo = 51 println("Part B magical answer is: ${replanterB.sumPotWithPlantNumbers() + (diffSettlesTo * (50000000000L - 98L))}") }