Advertisement
Guest User

Untitled

a guest
Dec 17th, 2023
193
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 4.34 KB | Source Code | 0 0
  1. package Y2023.D17
  2.  
  3. import Y2023.D17.Direction.*
  4. import java.lang.IllegalStateException
  5. import kotlin.math.min
  6.  
  7. class City(private val blocks: Map<Pair<Int, Int>, Int>) {
  8.  
  9.     fun navigate(): Int {
  10.         val heatLossMap = mutableMapOf<Triple<Pair<Int, Int>, Direction, Int>, Step>()
  11.         var leastHeatLoss = Int.MAX_VALUE
  12.         val goal = blocks.maxBy { it.key.first + it.key.second }!!.key
  13.         var options = listOf(
  14.             (0 to 1) to Step(0 to 1, 0, Right, 1, 0),
  15.             (1 to 0) to Step(1 to 0, 0, Down, 1, 0)
  16.         )
  17.         while (options.isNotEmpty()) {
  18.             val newOptions = mutableListOf<Pair<Pair<Int, Int>, Step>>()
  19.             options.forEach { option ->
  20.                 if (option.second.totalHeatLoss > leastHeatLoss) return@forEach
  21.                 val heatLossInCity = blocks[option.first] ?: -1
  22.                 if (heatLossInCity == -1) return@forEach
  23.  
  24.                 val cacheKey = Triple(option.first, option.second.direction, option.second.straight)
  25.                 if (heatLossMap[cacheKey]?.totalHeatLoss ?: Int.MAX_VALUE <= option.second.totalHeatLoss) return@forEach
  26.                 heatLossMap[cacheKey] = option.second
  27.  
  28.                 if (option.first == goal && option.second.afterTurn == 0) {
  29.                     leastHeatLoss = min(leastHeatLoss, option.second.totalHeatLoss + heatLossInCity)
  30.                     println("!!!")
  31.                     println(leastHeatLoss)
  32.                     println("!!!")
  33.                     return@forEach
  34.                 }
  35.                 if (option.second.straight != 9) newOptions += option.first + option.second.direction.moveForward() to option.second.goStraight(heatLossInCity)
  36.                 if (option.second.afterTurn > 0) return@forEach
  37.                 val clockwise = option.second.direction.turnCW()
  38.                 val counterClockwise = option.second.direction.turnCCW()
  39.                 newOptions += option.first + clockwise.moveForward() to option.second.turn(heatLossInCity, clockwise)
  40.                 newOptions += option.first + counterClockwise.moveForward() to option.second.turn(heatLossInCity, counterClockwise)
  41.             }
  42.             options = newOptions
  43.         }
  44.         return leastHeatLoss
  45.     }
  46.  
  47.     private fun paint(heatLossMap: MutableMap<Triple<Pair<Int, Int>, Direction, Int>, Step>, goal: Pair<Int, Int>) {
  48.         println(" D  U  L  R \t".repeat(goal.second + 1))
  49.         (0 .. goal.first).forEach {y ->
  50.             (0 .. goal.second).forEach {x ->
  51.                 val directions = listOf(Down, Up, Left, Right)
  52.                 val steps = 1..3
  53.                 directions.forEach {
  54.                     steps.forEach {step ->
  55.                         val message = "${heatLossMap[Triple((y to x),it,step)]?.totalHeatLoss ?: ""} "
  56.                         print(message.padStart(3, ' '))
  57.                     }
  58.                 }
  59.                 print("\t")
  60.             }
  61.             println()
  62.         }
  63.         println()
  64.     }
  65. }
  66.  
  67. data class Step(val block: Pair<Int, Int>, val totalHeatLoss: Int, val direction: Direction, val straight: Int, val afterTurn: Int) {
  68.     fun goStraight(heatLossInCity: Int) =
  69.         Step(block + direction.moveForward(), totalHeatLoss + heatLossInCity, direction, straight + 1, if (afterTurn == 0) 0 else afterTurn-1)
  70.  
  71.     fun turn(heatLossInCity: Int, newDirection: Direction): Step {
  72.         return Step(block + newDirection.moveForward(), totalHeatLoss + heatLossInCity, newDirection, 0, 3)
  73.     }
  74. }
  75.  
  76. enum class Direction {
  77.     Start, Right, Down, Left, Up;
  78.  
  79.     fun moveForward() =
  80.         when (this) {
  81.             Down -> 1 to 0
  82.             Up -> -1 to 0
  83.             Right -> 0 to 1
  84.             Left -> 0 to -1
  85.             Start -> throw IllegalStateException("Moved forward on Start")
  86.         }
  87.  
  88.     fun turnCCW() =
  89.         when (this) {
  90.             Down -> Right
  91.             Up -> Left
  92.             Right -> Up
  93.             Left -> Down
  94.             Start -> throw IllegalStateException("Moved forward on Start")
  95.         }
  96.  
  97.     fun turnCW() =
  98.         when (this) {
  99.             Down -> Left
  100.             Up -> Right
  101.             Right -> Down
  102.             Left -> Up
  103.             Start -> throw IllegalStateException("Moved forward on Start")
  104.         }
  105.  
  106. }
  107.  
  108. private operator fun Pair<Int, Int>.plus(other: Pair<Int, Int>) = this.first + other.first to this.second + other.second
  109.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement