• + 0 comments

    In scala recursion does not work, it is too slow, neither forward recursion with local memo, only backward GLOBAL recursion. I have added some fancy OOP for more readability.

    import scala.io.StdIn
    import scala.collection.mutable
    
    object Solution {
      private final case class Cell(
          row: Int,
          col: Int
      ) {
        def left: Cell = this.copy(col = col - 1)
        def upward: Cell = this.copy(row = row - 1)
      }
    
      private final case class Dice(
          top: Int,
          front: Int,
          left: Int
      ) {
        def rotateDown: Dice = this.copy(
          top = 7 - front,
          front = top
        )
        def rotateRight: Dice = this.copy(
          top = left,
          left = 7 - top
        )
      }
    
      private final case class Score(
          value: Int = 0
      ) {
        def +(dice: Dice): Score = this.copy(value = value + dice.top)
        def <(other: Score): Boolean = this.value < other.value
        def toInt: Int = value
      }
      private object Score {
        def apply(dice: Dice): Score = Score(dice.top)
        implicit val scoreOrdering: Ordering[Score] = Ordering.by(_.value)
        implicit def toInt(score: Score): Int = score.toInt
      }
    
      private val startCell = Cell(1, 1)
      private val initialDice = Dice(1, 2, 3)
      private val memo = mutable.Map[Cell, mutable.Map[Dice, Score]](
        startCell -> mutable.Map[Dice, Score](
          initialDice -> Score(initialDice)
        )
      )
    
      private def maximalPath(m: Int, n: Int): Int = {
        if ((m < 1) || (n < 1))
          return -1
    
        def calculate(cell: Cell): Unit = {
          if (!memo.contains(cell)) {
            memo.addOne(cell, mutable.Map.empty)
            if (1 < cell.row) {
              val upwardCell = cell.upward
              if (!memo.contains(upwardCell))
                calculate(upwardCell)
              memo(upwardCell).map { case (upwardDice, upwardScore) =>
                val dice = upwardDice.rotateDown
                val score = upwardScore + dice
                memo(cell).addOne(dice -> score)
              }
            }
            if (1 < cell.col) {
              val leftCell = cell.left
              if (!memo.contains(leftCell))
                calculate(leftCell)
              memo(leftCell).map { case (leftDice, leftScore) =>
                val dice = leftDice.rotateRight
                val score = leftScore + dice
                if (!memo(cell).contains(dice))
                  memo(cell).addOne(dice -> score)
                else if (memo(cell)(dice) < score)
                  memo(cell)(dice) = score
              }
            }
          }
        }
    
        val targetCell = Cell(m, n)
        calculate(targetCell)
        return memo(targetCell).values.max
      }
    
      def main(args: Array[String]): Unit = {
        val in = Iterator
          .continually(StdIn.readLine())
          .takeWhile(null != _)
          .map(_.trim)
        val t = in.next().toInt
        (1 to t)
          .map(_ => in.next().split(' ').map(_.toInt))
          .map(mn => maximalPath(mn.head, mn.last))
          .foreach(println)
      }
    }