ZigZag Conversion

The string “PAYPALISHIRING” is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)

P   A   H   N
A P L S I I G
Y   I   R

And then read line by line: “PAHNAPLSIIGYIR”

Write the code that will take a string and make this conversion given a number of rows:

convert(“PAYPALISHIRING”, 3)

should return

“PAHNAPLSIIGYIR”

def convert(s: String, numRows: Int): String = {
  numRows match {
    case 1 => s
    case n if n > 1 => {
      val lengthPerCycle = 2 * numRows - 2
      val cycles = (s.length / lengthPerCycle) + 1
      val sb = new StringBuilder
      for (i <- 0 until numRows) {
        for (cycle <- 0 until cycles) {
          // print full vertical
          val col = (cycle * lengthPerCycle) + i
          if (col < s.length)
            sb.append(s(col))
          // print diagonal
          val dia = ((cycle + 1) * lengthPerCycle) - i
          if (i != 0 && i < numRows - 1 && dia < s.length)
            sb.append(s(dia))
        }
      }
      sb.toString()
    }
    case _ => throw new Error("negative number")
  }
}

convert("PAYPALISHIRING", 3)