package aoc.thirteen import aoc.thirteen.Field import aoc.thirteen.Turn import aoc.thirteen.Train import java.io.File import java.io.InputStream class Main() { companion object { public var field: MutableList> = mutableListOf>() fun parseField(c: Char): Field { return when (c) { '|', 'v', '^' -> Field.VERTICAL '-', '>', '<' -> Field.HORIZONTAL '/' -> Field.TOP_LEFT '\\' -> Field.TOP_RIGHT '+' -> Field.INTERSECTION ' ' -> Field.EMPTY else -> throw IllegalArgumentException("can’t parse field " + c) } } fun cleanUpAfterCrash(trains: MutableList): Pair { for ((i, train) in trains.withIndex()) { for ((j, t2) in trains.withIndex()) { if (train != t2 && train.x == t2.x && train.y == t2.y) { return Pair(i, j) } } } return Pair(-1, -1) } fun parseTrain(c: Char, x: Int, y: Int): Train { val dir = when (c) { '^' -> 0 '>' -> 1 'v' -> 2 '<' -> 3 else -> throw IllegalArgumentException("this shouldn’t happen rooDerp") } return Train(dir, x, y) } fun moveTrain(t: Train): Train { when (t.direction) { 0 -> t.y -= 1 1 -> t.x += 1 2 -> t.y += 1 3 -> t.x -= 1 else -> throw IllegalArgumentException("this shouldn’t happen either selphyDerp") } val current = field[t.y][t.x] when (current) { Field.VERTICAL, Field.HORIZONTAL -> {} Field.TOP_LEFT -> t.direction = t.direction xor 1 Field.TOP_RIGHT -> t.direction = t.direction xor 3 Field.INTERSECTION -> t.crossIntersection() Field.EMPTY -> throw IllegalStateException("I shouldn’t be here") } return t } @JvmStatic fun main(args: Array) { val inputStream = File("input").inputStream() val inputLines = inputStream.bufferedReader().use { it.readText() }.split("\n") val TRAINS = charArrayOf('<', '>', '^', 'v') var trains = mutableListOf() for ((y, line) in inputLines.withIndex()) { var fields = mutableListOf() for ((x, char) in line.toCharArray().withIndex()) { if (char in TRAINS) { val newTrain = parseTrain(char, x, y) trains.add(newTrain) } fields.add(parseField(char)) } field.add(fields) } var positions = HashSet>(trains.size) positions.addAll(trains.map{ t -> Pair(t.x, t.y) }) var crash = false var remove = Pair(-1, -1) while (trains.size > 1) { for ((i, train) in trains.withIndex()) { trains[i] = moveTrain(train) positions.clear() positions.addAll(trains.map{ t -> Pair(t.x, t.y) }) // This is not ideal, but there is never more than one crash per tick if (trains.size > positions.size && !crash) { remove = cleanUpAfterCrash(trains) crash = true } } if (crash) { trains.removeAll(listOf(trains[remove.first], trains[remove.second])) crash = false } trains = trains.sortedBy{ it.y * 200 + it.x }.toMutableList() } println("${trains[0].x},${trains[0].y}") } } }