• + 0 comments

    scala, building rings, reducing cycles in rings, linear.

    import scala.io.StdIn
    
    object Solution {
      private object Move {
        val down = (1, 0)
        val right = (0, 1)
        val up = (-1, 0)
        val left = (0, -1)
      }
    
      private def rotate(r: Int, matrix: Seq[Seq[Int]]): Seq[Seq[Int]] = {
        if (r < 1)
          return matrix
        val m = matrix.length
        val n = matrix.head.length
        val c = math.min(m, n) / 2
        val rotated = Array.ofDim[Int](m, n)
        (0 until c)
          .map { i =>
            val rows = m - 2 * i
            val cols = n - 2 * i
            val cells = 2 * rows + 2 * cols - 4
            val leftTop = (i, i)
            val leftBottom = (i + rows - 1, i)
            val rightBottom = (i + rows - 1, i + cols - 1)
            val rightTop = (i, i + cols - 1)
            (1 until cells)
              .scanLeft(leftTop -> Move.down) { case ((cell, move), _) =>
                val nextCell = (cell._1 + move._1) -> (cell._2 + move._2)
                val nextMove = nextCell match {
                  case `leftBottom`  => Move.right
                  case `rightBottom` => Move.up
                  case `rightTop`    => Move.left
                  case `leftTop`     => Move.down
                  case _             => move
                }
                nextCell -> nextMove
              }
              .map(_._1)
          }
          .foreach { ring =>
            val split = r % ring.length
            (ring zip (ring.drop(split) ++ ring.take(split)))
              .foreach { case (sourceCell, targetCell) =>
                rotated(targetCell._1)(targetCell._2) = matrix(sourceCell._1)(sourceCell._2)
              }
          }
        return rotated.map(_.toSeq).toSeq
      }
    
      def main(args: Array[String]): Unit = {
        val in = Iterator
          .continually(StdIn.readLine())
          .takeWhile(null != _)
          .map(_.trim)
        val mnr = in.next().split(' ').map(_.toInt)
        val m = mnr.head
        val r = mnr.last
        val arr = (1 to m)
          .map(_ => in.next().split(' ').map(_.toInt).toSeq)
          .toSeq
        println(
          rotate(r, arr)
            .map(_.mkString(" "))
            .mkString("\n")
        )
      }
    }