Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package Y2024.D20
- import kotlin.math.abs
- class RaceCondition(val lines: List<String>) {
- private val width = lines[0].length
- private val height = lines.size
- private val startY= lines.indexOfFirst { it.contains("S") }
- private val startX = lines[startY].indexOf('S')
- private val stepOnPositions = mutableMapOf<Pair<Int, Int>, Int>()
- fun runWhileCheating(distance: Int, minimalGain: Int): Int {
- var cheatCount = 0
- var step = 0
- var pos: Pair<Int, Int>? = startY to startX
- var prevPos = -1 to -1
- do {
- pos!!
- stepOnPositions[pos] = step
- cheatCount += pos.neighboursADistance(step, distance, minimalGain)
- step ++
- val previous = pos
- pos = pos.next(prevPos)
- prevPos = previous
- } while (pos != null)
- return cheatCount
- }
- private fun Pair<Int, Int>.next(prevPos: Pair<Int, Int>): Pair<Int, Int>? {
- return when {
- isValidTile(this + (1 to 0), prevPos) -> this + (1 to 0)
- isValidTile(this + (0 to 1), prevPos) -> this + (0 to 1)
- isValidTile(this + (-1 to 0), prevPos) -> this + (-1 to 0)
- isValidTile(this + (0 to -1), prevPos) -> this + (0 to -1)
- else -> null
- }
- }
- private fun Pair<Int, Int>.neighboursADistance(step: Int, distance: Int, minimalGain: Int): Int {
- var count = 0
- (-distance..distance).forEach { yOffset ->
- val xDistance = distance - abs(yOffset)
- (-xDistance..xDistance).forEach { xOffset ->
- stepOnPositions[this.first + yOffset to this.second + xOffset]?.let { otherStep ->
- val savedSteps = step - otherStep - abs(yOffset) - abs(xOffset)
- if (savedSteps >= minimalGain) count++
- }
- }
- }
- return count
- }
- private fun isValidTile(tile: Pair<Int, Int>, prevPos: Pair<Int, Int>) =
- prevPos != tile && lines[tile.first][tile.second] != '#'
- private operator fun Pair<Int, Int>.plus(other: Pair<Int, Int>): Pair<Int, Int> {
- return first + other.first to second + other.second
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement