Advertisement
roachls

Grid

Feb 1st, 2019
421
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 3.06 KB | None | 0 0
  1. package org.roach.nonogramsolver
  2. import collection.LinearSeq
  3. /**
  4.  * The Grid is a list of rows.
  5.  */
  6. case class Grid private (val contents: List[Row]) extends LinearSeq[Row] {
  7.   /**
  8.    * Get the row at the specified index
  9.    * @param index The row number to get
  10.    */
  11.   def apply(idx: Int) = {
  12.     if (idx < 0 || length <= idx)
  13.       throw new IndexOutOfBoundsException
  14.     contents(idx)
  15.   }
  16.   /**
  17.    * Get the column at the specified index
  18.    * @param index The column number to get
  19.    */
  20.   def getCol(index: Int): Row = Row((for(row <- contents) yield row(index)): _*)
  21.  
  22.   /**
  23.    * Converts the Grid to a string for printing
  24.    */
  25.   override def toString = contents.mkString("\n")
  26.  
  27.   /**
  28.    * Retrieves the length of the Grid.
  29.    */
  30.   val length = contents.length
  31.  
  32.   /**
  33.    * Returns a new Grid with the specified row replacing the row at the specified index.
  34.    * @param index The position to place the new row
  35.    * @param insertRow The row to patch in.
  36.    */
  37.   def updated(index: Int, insertRow: Row) = Grid(contents.updated(index, insertRow))
  38.  
  39.   /**
  40.    * Returns a new Grid with rows and columns reversed.
  41.    */
  42.   lazy val inverse: Grid = Grid(
  43.     (for (c <- 0 until contents.length) yield getCol(c)).toList
  44.   )
  45.  
  46.   /**
  47.    * Returns a heuristic number indicating approximately how different this grid
  48.    * is from the given list of column Requirements
  49.    * @param colReqs The list of column Requirements
  50.    * @return The sum of the absolute values of diffs for each column
  51.    */
  52.   def columnDiff(colReqs: List[Requirement]) = (for ((col, req) <- this.inverse.contents zip colReqs) yield col.diff(req)).sum
  53.  
  54.   /**
  55.    * Returns a new grid merged with this one to be used as a filter.
  56.    * Works as such:
  57.    * O + O = O
  58.    * X + X = X
  59.    * O + U = U + O = O
  60.    * X + U = U + X = X
  61.    * U + U = U
  62.    * O + X = X + O = E (throw new ImpossibleException)
  63.    * E + ? = E
  64.    */
  65.   def & (that: Grid): Grid = new Grid((contents, that.contents).zipped.map((r, t) => r & t))
  66.  
  67.   /**
  68.    * Applies rules to the grid to make a new filter
  69.    * <ol>
  70.    *  <li>Invert the grid so that the columns are now rows</li>
  71.    *  <li>Apply rules to each row using map</li>
  72.    *  <li>Create a new Grid from the applied rows</li>
  73.    *  <li>Re-invert the grid and return it
  74.    * </ol>
  75.    */
  76.   def applyRules(reqs: List[Requirement]): Grid = {
  77.     val rowList = for ((row, req) <- inverse.contents zip reqs) yield Row.applyRules(row, req)
  78.     Grid(rowList).inverse
  79.   }
  80.  
  81.   override def equals(obj: Any) = obj match {
  82.     case otherGrid: Grid => contents.equals(otherGrid.contents)
  83.     case _ => false
  84.   }
  85.  
  86.   val hasErrors = {
  87.     var b = false
  88.     for (i <- 0 to size - 1) {
  89.       b |= contents(i).isErrorRow
  90.     }
  91.     b
  92.   }
  93. }
  94.  
  95. object Grid {
  96.   /**
  97.    * Creates an empty grid with all characters unknown
  98.    * @param size The width and length of the new Grid
  99.    */
  100.   def emptyGrid(size:Int) = new Grid(List.fill(size)(Row.emptyRow(size)))
  101.  
  102.   def fromSeq(buf: Seq[Row]): Grid = {
  103.     new Grid(buf.toList)
  104.   }
  105.  
  106.  
  107.   def apply(rows: Row*) = fromSeq(rows)
  108. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement