Advertisement
Guest User

Untitled

a guest
Aug 20th, 2016
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 3.10 KB | None | 0 0
  1. object Solution {
  2.  
  3.   import scala.io.StdIn._
  4.  
  5.   def main(args: Array[String]): Unit = {
  6.  
  7.     val params = readLine().split("\\s").toList
  8.  
  9.     params match {
  10.       case r :: c :: n :: Nil if r.toInt > 0 && c.toInt > 0 && c.toInt <= 200 && n.toInt > 0 && n.toInt < 1000000000 =>
  11.         //Define regex matcher to validate input
  12.         val fmt = s"""^[O.]{$c}""".r
  13.         val inputOption = (0 until r.toInt).foldLeft(Option("")) { (str, _) =>
  14.           val line = readLine()
  15.           if(fmt.pattern.matcher(line).matches)
  16.             str.map(_ + line)
  17.           else None
  18.         }
  19.         val input = inputOption.getOrElse {
  20.           throw new IllegalArgumentException("Input was not in the expected format")
  21.         }
  22.         val grid = Grid(r.toInt, c.toInt, input.map((_, 0)).toVector)
  23.         //Print grid after N ticks
  24.         println(gridAtN(grid, n.toInt))
  25.       case _ => throw new IllegalArgumentException("Input was not in expected format")
  26.     }
  27.  
  28.   }
  29.  
  30.   type Time = Int
  31.  
  32.   case class Grid(numRows: Int, numColumns: Int, cells: Vector[(Char, Time)]) {
  33.     override def toString: String = cells.grouped(numColumns).foldLeft("") { (str, line) =>
  34.       str + line.map(_._1).mkString("") + sys.props("line.separator")
  35.     }
  36.   }
  37.  
  38.   val tick = (previousGrid: Grid, time: Time) => {
  39.     if (time == 1)
  40.       previousGrid
  41.     else if (time % 2 == 0) {
  42.       //Every second tick, fill entire grid with bombs
  43.       //Par as an optimisation here, but is likely to be worse on small vectors so put in a threshold
  44.       previousGrid.copy(cells = previousGrid.cells.map(cell => if (cell._1 != 'O') ('O', time) else cell))
  45.     } else {
  46.       //Otherwise we're on a tick which is "odd", corresponding to step 4: Kaboom!
  47.       previousGrid.cells.zipWithIndex.foldLeft(previousGrid) { case (g, (cell, idx)) =>
  48.         if(cell._1 == 'O' && time - cell._2 == 3) detonate(g, idx / g.numColumns, idx % g.numColumns, time) else g
  49.       }
  50.     }
  51.   }
  52.  
  53.   def getCellOption(grid: Grid, i: Int, j: Int) = {
  54.     if(i < 0 || i >= grid.numRows || j < 0 || j >= grid.numColumns)
  55.       None
  56.     else
  57.       Some((i * grid.numColumns) + j)
  58.   }
  59.  
  60.   def detonate(grid: Grid, i: Int, j: Int, t: Time): Grid = getCellOption(grid, i, j).fold(grid) { cellIdx =>
  61.     grid.cells.lift(cellIdx).fold(grid) {
  62.  
  63.       case ('O', age) =>
  64.         //There is a bomb
  65.         //Is the bomb exactly 3 seconds old?
  66.         val newGrid = grid.copy(cells = grid.cells.updated(cellIdx, ('.', t)))
  67.         if (t - age == 3) {
  68.           //If so then spread to bomb's neighbours after updating this cell
  69.           //Multiple vals chaining dependency on new grid created after each detonation. Would use for comprehension and
  70.           //flatmap over cells vector in a redesign
  71.           val n = detonate(newGrid, i-1, j, t)
  72.           val e = detonate(n, i, j+1, t)
  73.           val s = detonate(e, i+1, j, t)
  74.           detonate(s, i, j-1, t) //w
  75.         } else {
  76.           newGrid
  77.         }
  78.       case _ => grid //There was no bomb in that slot.
  79.     }
  80.   }
  81.  
  82.   def gridAtN(grid: Grid, n: Time): Grid = Iterator.from(1).take(n).foldLeft(grid)(tick)
  83. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement