diff options
author | tchojnacki <tomaszchojnacki2001@gmail.com> | 2022-08-11 19:24:23 +0200 |
---|---|---|
committer | tchojnacki <tomaszchojnacki2001@gmail.com> | 2022-08-11 19:24:23 +0200 |
commit | 0f1e145b80813ae2331b7dac5ace0c589654ad2a (patch) | |
tree | 25483b8239436dd5aed2fee8811caf0ba893c0bb /aoc-2021-kotlin/src/Day25.kt | |
parent | 85fb0396bed6a2129b12392941103924b1ab55be (diff) | |
download | gleam_aoc2020-0f1e145b80813ae2331b7dac5ace0c589654ad2a.tar.gz gleam_aoc2020-0f1e145b80813ae2331b7dac5ace0c589654ad2a.zip |
Move subproject to avoid IntelliJ module name issues
Diffstat (limited to 'aoc-2021-kotlin/src/Day25.kt')
-rw-r--r-- | aoc-2021-kotlin/src/Day25.kt | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/aoc-2021-kotlin/src/Day25.kt b/aoc-2021-kotlin/src/Day25.kt new file mode 100644 index 0000000..36a2f75 --- /dev/null +++ b/aoc-2021-kotlin/src/Day25.kt @@ -0,0 +1,87 @@ +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 '.'!") + } + }) + } + } + + 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 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 } + } + } + + private fun stepOnce() { + stepDirection<SeaTile.Cucumber.EastFacing>(Pos2D(1, 0)) + stepDirection<SeaTile.Cucumber.SouthFacing>(Pos2D(0, 1)) + } + + fun simulate(): Int { + var count = 0 + + do { + val previousHashCode = matrix.contentHashCode() + stepOnce() + count++ + } while (matrix.contentHashCode() != previousHashCode) + + 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 "") + } + } + + fun singlePart(input: List<String>) = SeaCucumbers.fromLines(input).simulate() +} + +fun main() { + val testInput = readInputAsLines("Day25_test") + check(Day25.singlePart(testInput) == 58) + + val input = readInputAsLines("Day25") + println(Day25.singlePart(input)) +} |