diff options
Diffstat (limited to 'src/Day25.kt')
-rw-r--r-- | src/Day25.kt | 136 |
1 files changed, 69 insertions, 67 deletions
diff --git a/src/Day25.kt b/src/Day25.kt index 309c15e..36a2f75 100644 --- a/src/Day25.kt +++ b/src/Day25.kt @@ -1,85 +1,87 @@ -class SeaCucumbers(private val width: Int, private val height: Int, private val matrix: Array<SeaTile>) { - companion object { - fun fromLines(lines: List<String>) = - Pos2D( - lines.getOrNull(0)?.length ?: throw IllegalArgumentException("Sea must have a non-zero height!"), - lines.size - ).let { size -> - SeaCucumbers(size.x, size.y, Array(size.x * size.y) { - when (val char = lines[it / size.x][it % size.x]) { - '>' -> SeaTile.Cucumber.EastFacing - 'v' -> SeaTile.Cucumber.SouthFacing - '.' -> SeaTile.EmptyTile - else -> throw IllegalArgumentException("Found '$char', expected '>', 'v' or '.'!") - } - }) - } - } +object Day25 { + private class SeaCucumbers(private val width: Int, private val height: Int, private val matrix: Array<SeaTile>) { + companion object { + fun fromLines(lines: List<String>) = + Pos2D( + lines.getOrNull(0)?.length ?: throw IllegalArgumentException("Sea must have a non-zero height!"), + lines.size + ).let { size -> + SeaCucumbers(size.x, size.y, Array(size.x * size.y) { + when (val char = lines[it / size.x][it % size.x]) { + '>' -> SeaTile.Cucumber.EastFacing + 'v' -> SeaTile.Cucumber.SouthFacing + '.' -> SeaTile.EmptyTile + else -> throw IllegalArgumentException("Found '$char', expected '>', 'v' or '.'!") + } + }) + } + } - sealed class SeaTile { - object EmptyTile : SeaTile() - sealed class Cucumber : SeaTile() { - object EastFacing : Cucumber() - object SouthFacing : Cucumber() + private sealed class SeaTile { + object EmptyTile : SeaTile() + sealed class Cucumber : SeaTile() { + object EastFacing : Cucumber() + object SouthFacing : Cucumber() + } } - } - private fun moveIndex(index: Int, offset: Pos2D) = - ((index / width + offset.y) % height) * width + (index + offset.x) % width + private fun moveIndex(index: Int, offset: Pos2D) = + ((index / width + offset.y) % height) * width + (index + offset.x) % width - private inline fun <reified T : SeaTile.Cucumber> stepDirection(pos: Pos2D) { - matrix - .asSequence() - .withIndex() - .map { (index, seaTile) -> - val nextIndex = moveIndex(index, pos) - if (seaTile is T && matrix[nextIndex] is SeaTile.EmptyTile) { - index to nextIndex - } else { - null + private inline fun <reified T : SeaTile.Cucumber> stepDirection(pos: Pos2D) { + matrix + .asSequence() + .withIndex() + .map { (index, seaTile) -> + val nextIndex = moveIndex(index, pos) + if (seaTile is T && matrix[nextIndex] is SeaTile.EmptyTile) { + index to nextIndex + } else { + null + } } - } - .filterNotNull() - .toList() - .forEach { (index, nextIndex) -> - matrix[nextIndex] = matrix[index].also { matrix[index] = SeaTile.EmptyTile } - } - } + .filterNotNull() + .toList() + .forEach { (index, nextIndex) -> + matrix[nextIndex] = matrix[index].also { matrix[index] = SeaTile.EmptyTile } + } + } - private fun stepOnce() { - stepDirection<SeaTile.Cucumber.EastFacing>(Pos2D(1, 0)) - stepDirection<SeaTile.Cucumber.SouthFacing>(Pos2D(0, 1)) - } + private fun stepOnce() { + stepDirection<SeaTile.Cucumber.EastFacing>(Pos2D(1, 0)) + stepDirection<SeaTile.Cucumber.SouthFacing>(Pos2D(0, 1)) + } - fun simulate(): Int { - var count = 0 + fun simulate(): Int { + var count = 0 - do { - val previousHashCode = matrix.contentHashCode() - stepOnce() - count++ - } while (matrix.contentHashCode() != previousHashCode) + do { + val previousHashCode = matrix.contentHashCode() + stepOnce() + count++ + } while (matrix.contentHashCode() != previousHashCode) - return count + return count + } + + override fun toString(): String = matrix + .withIndex() + .joinToString("") { (index, seaTile) -> + when (seaTile) { + SeaTile.Cucumber.EastFacing -> ">" + SeaTile.Cucumber.SouthFacing -> "v" + SeaTile.EmptyTile -> "." + } + (if (index % width == width - 1) "\n" else "") + } } - override fun toString(): String = matrix - .withIndex() - .joinToString("") { (index, seaTile) -> - when (seaTile) { - SeaTile.Cucumber.EastFacing -> ">" - SeaTile.Cucumber.SouthFacing -> "v" - SeaTile.EmptyTile -> "." - } + (if (index % width == width - 1) "\n" else "") - } + fun singlePart(input: List<String>) = SeaCucumbers.fromLines(input).simulate() } fun main() { - fun calculate(input: List<String>) = SeaCucumbers.fromLines(input).simulate() - val testInput = readInputAsLines("Day25_test") - check(calculate(testInput) == 58) + check(Day25.singlePart(testInput) == 58) val input = readInputAsLines("Day25") - println(calculate(input)) + println(Day25.singlePart(input)) } |