Coverage Summary for Class: Day14p2Kt (day14p2)

Class Method, % Line, %
Day14p2Kt 100% (1/1) 100% (1/1)
Day14p2Kt$toPlatform$1 100% (1/1) 100% (1/1)
Total 100% (2/2) 100% (2/2)


 package day14p2
 
 fun String.toPlatform(): Platform = Platform(lineSequence().map { it.toMutableList() }.toList())
 
 data class Platform(val value: List<MutableList<Char>>) {
   private val numOfColumns = value.first().size
   private val numOfRows = value.size
 
   fun deepCopy(): Platform = Platform(value.map { it.toMutableList() })
 
   fun tiltNorth(): Platform {
     for (col in (0..<numOfColumns)) {
       for (row in value.indices) {
         var currentRow = row
         while (currentRow > 0 && value[currentRow - 1][col] == '.' && value[currentRow][col] == 'O') {
           this.value[currentRow - 1][col] = 'O'
           this.value[currentRow][col] = '.'
           currentRow--
         }
       }
     }
 
     return this
   }
 
   fun tiltWest(): Platform {
     for (row in value.indices) {
       for (col in (0..<numOfColumns)) {
         var currentCol = col
         while (currentCol > 0 && value[row][currentCol - 1] == '.' && value[row][currentCol] == 'O') {
           this.value[row][currentCol - 1] = 'O'
           this.value[row][currentCol] = '.'
           currentCol--
         }
       }
     }
 
     return this
   }
 
   fun tiltSouth(): Platform {
     for (col in (0..<numOfColumns)) {
       for (row in value.indices.reversed()) {
         var currentRow = row
         while (currentRow < numOfRows - 1 && value[currentRow + 1][col] == '.' && value[currentRow][col] == 'O') {
           this.value[currentRow + 1][col] = 'O'
           this.value[currentRow][col] = '.'
           currentRow++
         }
       }
     }
 
     return this
   }
 
   fun tiltEast(): Platform {
     for (row in value.indices) {
       for (col in (0..<numOfColumns).reversed()) {
         var currentCol = col
         while (currentCol < numOfColumns - 1 && value[row][currentCol + 1] == '.' && value[row][currentCol] == 'O') {
           value[row][currentCol + 1] = 'O'
           value[row][currentCol] = '.'
           currentCol++
         }
       }
     }
 
     return this
   }
 
   fun spin(cycles: Int, cache: MutableMap<Pair<Platform, Int>, Platform> = mutableMapOf()): Platform {
     if (cycles == 0) return this
 
     val key = this to cycles
     cache[key]?.let {
       return it
     }
 
     val newPlatform = if (cycles == 1) spinOnce() else {
       val half = cycles / 2
       val remaining = cycles - half
 
       spin(half, cache).spin(remaining, cache)
     }
 
     cache[key] = newPlatform
 
     return newPlatform
   }
 
   private fun spinOnce(): Platform = deepCopy().tiltNorth().tiltWest().tiltSouth().tiltEast()
 
   fun look(): String = value.joinToString("\n") { it.joinToString("") }
   fun calcTotalLoad(): Long {
     val numOfRows = value.size.toLong()
 
     return value.asSequence().mapIndexed { rowIndex, row ->
       val load = numOfRows - rowIndex
       row.sumOf { if (it == 'O') load else 0 }
     }.sum()
   }
 }