|
| 1 | +package de.ronny_h.aoc.year2017.day25 |
| 2 | + |
| 3 | +import de.ronny_h.aoc.AdventOfCode |
| 4 | +import de.ronny_h.aoc.extensions.collections.split |
| 5 | +import de.ronny_h.aoc.year2017.day25.TapeDirection.LEFT |
| 6 | +import de.ronny_h.aoc.year2017.day25.TapeDirection.RIGHT |
| 7 | + |
| 8 | +fun main() = TheHaltingProblem().run(2794, 0) |
| 9 | + |
| 10 | +class TheHaltingProblem : AdventOfCode<Int>(2017, 25) { |
| 11 | + override fun part1(input: List<String>): Int = TuringMachine(input.parseTuringMachineConfiguration()).run() |
| 12 | + override fun part2(input: List<String>): Int = 0 |
| 13 | +} |
| 14 | + |
| 15 | +fun List<String>.parseTuringMachineConfiguration(): TuringMachineConfiguration { |
| 16 | + val startState = first().substringAfter("Begin in state ").substringBefore(".") |
| 17 | + val checkAfter = this[1].substringAfter("Perform a diagnostic checksum after ").split(" ").first().toInt() |
| 18 | + |
| 19 | + val rules = subList(3, size).split().flatMap { rule -> |
| 20 | + val inState = rule[0].substringAfter("In state ").trim(':') |
| 21 | + listOf(rule.parseRule(inState, 1), rule.parseRule(inState, 5)) |
| 22 | + } |
| 23 | + |
| 24 | + return TuringMachineConfiguration(startState, checkAfter, rules) |
| 25 | +} |
| 26 | + |
| 27 | +private fun List<String>.parseRule( |
| 28 | + inState: String, |
| 29 | + offset: Int, |
| 30 | +): Rule { |
| 31 | + val value = this[offset].substringAfter(" If the current value is ").trim(':').toByte() |
| 32 | + val toWrite = this[offset + 1].substringAfter(" - Write the value ").trim('.').toByte() |
| 33 | + val toMove = if (this[offset + 2].endsWith("right.")) RIGHT else LEFT |
| 34 | + val nextState = this[offset + 3].substringAfter(" - Continue with state ").trim('.') |
| 35 | + return Rule(inState, value, toWrite, toMove, nextState) |
| 36 | +} |
| 37 | + |
| 38 | +data class TuringMachineConfiguration(val startState: String, val checkAfter: Int, val rules: List<Rule>) |
| 39 | + |
| 40 | +data class Rule( |
| 41 | + val inState: String, |
| 42 | + val value: Byte, |
| 43 | + val toWrite: Byte, |
| 44 | + val toMove: TapeDirection, |
| 45 | + val nextState: String, |
| 46 | +) |
| 47 | + |
| 48 | +enum class TapeDirection(val offset: Int) { |
| 49 | + LEFT(-1), RIGHT(1) |
| 50 | +} |
| 51 | + |
| 52 | +class TuringMachine(private val configuration: TuringMachineConfiguration) { |
| 53 | + private val tape = mutableMapOf<Int, Byte>().withDefault { 0 } |
| 54 | + private var cursor = 0 |
| 55 | + private var state = configuration.startState |
| 56 | + |
| 57 | + private val rules = configuration.rules.associateBy { Pair(it.inState, it.value) } |
| 58 | + |
| 59 | + fun run(): Int { |
| 60 | + repeat(configuration.checkAfter) { |
| 61 | + val rule = rules.getValue(Pair(state, tape.getValue(cursor))) |
| 62 | + tape[cursor] = rule.toWrite |
| 63 | + cursor += rule.toMove.offset |
| 64 | + state = rule.nextState |
| 65 | + } |
| 66 | + return tape.values.count { it == 1.toByte() } |
| 67 | + } |
| 68 | +} |
0 commit comments