roachls

Row_updated

Feb 2nd, 2019
173
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 8.41 KB | None | 0 0
  1. package org.roach.nonogramsolver
  2. import collection.mutable.ListBuffer
  3. import collection.SeqLike
  4.  
  5. abstract class Cell {
  6.   def &(other: Cell): Cell = Cell.fromInt(Cell.toInt(this) & Cell.toInt(other))
  7.   def &&(other: Cell): Cell = if (this == other) this else U
  8. }
  9. // Error
  10. case object E extends Cell
  11. // Cell is definitely marked
  12. case object X extends Cell {
  13.   override val toString = " "
  14. }
  15. // Cell is definitely unmarked
  16. case object O extends Cell {
  17.   override val toString = "*"
  18. }
  19. // Cell is unknown
  20. case object U extends Cell
  21.  
  22. object Cell {
  23.   val fromInt: Int => Cell = Array(E, O, X, U)
  24.   val toInt: Cell => Int = Map(E -> 0, O -> 1, X -> 2, U -> 3)
  25. }
  26.  
  27. import collection.IndexedSeqLike
  28. import collection.mutable.{ Builder, ArrayBuffer }
  29. import collection.generic.CanBuildFrom
  30. import collection.immutable.LinearSeq
  31.  
  32. class Row(
  33.   val _cellList: List[Cell]) extends LinearSeq[Cell] with SeqLike[Cell, Row] {
  34.   implicit def listToRow(l: List[Cell]) = new Row(l)
  35.   import Row._
  36.   override protected[this] def newBuilder: Builder[Cell, Row] =
  37.     Row.newBuilder
  38.   override def reverse = Row(_cellList.reverse)
  39.   def contains(c: Cell) = _cellList.contains(c)
  40.   def indexOf(c: Cell) = _cellList.indexOf(c)
  41.   override def drop(num: Int) = Row(_cellList drop num)
  42.   override def take(num: Int) = Row(_cellList take num)
  43.   def updated(index: Int, elem: Cell) = Row(_cellList.updated(index, elem))
  44.   override def lengthCompare(len: Int): Int = _cellList.lengthCompare(len)
  45.   override def isEmpty = _cellList.isEmpty
  46.   override def head = _cellList.head
  47.   override def tail = _cellList.tail
  48.   override def length = _cellList.length
  49.   def apply(idx: Int): Cell = _cellList(idx)
  50.   override def foreach[T](f: Cell => T): Unit = _cellList.foreach { f }
  51.  
  52.   val countOs = _cellList.count(c => c == O)
  53.  
  54.   val isErrorRow = (_cellList.count(c => c == E)) > 0
  55.  
  56.   def compatibleWith(filter: Row) = (this.groups, filter.groups).zipped.forall((r, f) => (r | f) == f)
  57.  
  58.   def diff(req: Requirement) = scala.math.abs(countOs - req.sum)
  59.  
  60.   override lazy val toString: String = (for (idx <- 0 until length) yield this(idx).toString).mkString
  61.  
  62.   def &(that: Row): Row = Row((this._cellList, that._cellList).zipped.map((r, o) => r & o))
  63.   def &&(that: Row): Row = Row((this._cellList, that._cellList).zipped.map((r, o) => r && o))
  64.  
  65.   def actual: Requirement = {
  66.     if (!_cellList.contains(O))
  67.       return Requirement()
  68.  
  69.     var lb = _actual(this)
  70.     return Requirement(lb)
  71.   }
  72.  
  73.   def groups(): Array[Int] = {
  74.     val g = new Array[Int]((_cellList.length + N - 1) / N)
  75.     for (i <- 0 until _cellList.length) {
  76.       g(i / N) |= Cell.toInt(_cellList(i)) << (i % N * S)
  77.     }
  78.     g
  79.   }
  80.  
  81.   def ++(otherRow: Row): Row = Row(this._cellList ++ otherRow._cellList)
  82. }
  83.  
  84. object Row {
  85.   private val S = 2
  86.   private val N = 32 / S
  87.   private val M = (1 << S) - 1
  88.  
  89.   def fromSeq(buf: Seq[Cell]): Row =
  90.     new Row(buf.toList)
  91.  
  92.   def apply(cells: Cell*) = fromSeq(cells)
  93.   def apply(ab: ArrayBuffer[Cell]) = fromSeq(ab)
  94.   def apply(ab: List[Cell]) = fromSeq(ab)
  95.  
  96.   def newBuilder: Builder[Cell, Row] = new ArrayBuffer mapResult fromSeq
  97.  
  98.   implicit def canBuildFrom: CanBuildFrom[Row, Cell, Row] =
  99.     new CanBuildFrom[Row, Cell, Row] {
  100.       def apply(): Builder[Cell, Row] = newBuilder
  101.       def apply(from: Row): Builder[Cell, Row] = newBuilder
  102.     }
  103.   def emptyRow(length: Int) = Row(Array.fill(length)(U): _*)
  104.   def ErrorRow(length: Int) = Row(Array.fill(length)(E): _*)
  105.  
  106.   def applyRules(row: Row, req: Requirement): Row = {
  107.     val retforwards = rule3(row, req)
  108.     val retbackwards = rule3(row.reverse, req.reverse).reverse
  109.     val ret = retforwards & retbackwards
  110.     if (ret contains E) ErrorRow(row.length) else ret
  111.   }
  112.  
  113.   private def _actual(row: Row): ListBuffer[Int] = {
  114.     var lb: ListBuffer[Int] = ListBuffer[Int]()
  115.     if (!row.contains(O)) return lb
  116.     var pos = row.indexOf(O)
  117.     var count = 0
  118.     while (pos < row.length && row(pos) == O) {
  119.       count += 1
  120.       pos += 1
  121.     }
  122.     lb += count
  123.     if (pos + 1 < row.length)
  124.       lb ++= _actual(row drop pos + 1)
  125.     lb
  126.   }
  127.  
  128.   def rule3(row: Row, req: Requirement): Row = {
  129.     var isProblematic = false
  130.     //    println(s"in= $row, req=$req")
  131.  
  132.     if (req.gamesum > row.length) return ErrorRow(row.length)
  133.     if (req.gamesum == row.length) {
  134.       // requirements exactly met
  135.       return row & req.generateFilter(row.size)
  136.     }
  137.     if (req isEmpty) {
  138.       return row & Row.fill(row.length)(X)
  139.     }
  140.     if (row.forall(_ == U)) { // ab is only U
  141.       return req.generateFilter(row.length)
  142.     }
  143.     val firstO = First(O)
  144.  
  145.     val ret = row._cellList match {
  146.       case Nil => Row()
  147.       case r if r contains E => row
  148.       case X :: tail => (row take 1) ++ rule3(Row(tail), req)
  149.       case O :: tail => {
  150.         val req1 = req.head
  151.         var ab = ArrayBuffer[Cell](row: _*)
  152.         ab = fill(ab, 0, req1 - 1, O)
  153.         if (req1 < ab.length) ab(req1) &= X
  154.         Row(ab.take(req1 + 1)) ++ rule3(row.drop(req1 + 1), req.tail)
  155.       }
  156.       case _ :: O :: _ :: tail if req.head == 1 =>
  157.         ((row take 3) & Row(X, O, X)) ++ rule3(Row(tail), req.tail)
  158.       case list if list contains O => {
  159.         var ab = ArrayBuffer[Cell](row: _*)
  160.         val pos = list.indexOf(O)
  161.         val req1 = req.head
  162.         if (list contains X) {
  163.           val xPos = list.indexOf(X)
  164.           if (xPos == pos + 1) {
  165.             val start = pos - req1 + 1
  166.             if (start < 0) return ErrorRow(row.length)
  167.             if (req.length > 1) {
  168.               // partition req into parts that fit and try each
  169.               val leftHalf = row take xPos
  170.               val rightHalf = row drop xPos + 1
  171.               var tryRow: Row = null
  172.               for (i <- 0 to req.length) {
  173.                 val (lpart, rpart) = req.splitAt(i)
  174.                 val tryPartRow = applyRules(leftHalf, lpart) ++ Row(X) ++ applyRules(rightHalf, rpart)
  175.                 tryRow = tryRow match {
  176.                   case null => if (!(tryPartRow contains E)) tryPartRow else null
  177.                   case _ => if (!(tryPartRow contains E)) tryRow && tryPartRow else tryRow
  178.                 }
  179.               }
  180.               return tryRow
  181.             } else if (req.length == 1) {
  182.               if (start > 0)
  183.                 ab = fill(ab, 0, start - 1, X)
  184.               if (start >= 0)
  185.                 ab = fill(ab, start, pos - 1, O)
  186.               if (pos + 1 < ab.length)
  187.                 ab = fill(ab, pos + 1, ab.length - 1, X)
  188.             }
  189.           }
  190.         } else if (pos <= req1 - 1) {
  191.           ab = fill(ab, pos, req1 - 1, O)
  192.           if (pos == 0 && req1 < row.length) {
  193.             ab(req1) &= X
  194.           }
  195.           if (req.size > 1) {
  196.             //         TODO problematic for 10
  197.             //            //          println("About to call rule3 recursively")
  198.             //            ab = ab.take(req1) ++ ArrayBuffer(rule3(row drop req1, req.tail): _*)
  199.           } else
  200.             ab = fill(ab, req1 + pos, row.length - 1, X)
  201.         }
  202.         if (isProblematic) println(s"ab = $ab")
  203.         Row(ab)
  204.       }
  205.       case list if list contains X => {
  206.         val xPos = list.indexOf(X)
  207.         // partition req into parts that fit and try each
  208.         val leftHalf = row take xPos
  209.         val rightHalf = row drop xPos + 1
  210.         var tryRow: Row = null
  211.         for (i <- 0 to req.length) {
  212.           val (lpart, rpart) = req.splitAt(i)
  213.           val tryPartRow = applyRules(leftHalf, lpart) ++ Row(X) ++ applyRules(rightHalf, rpart)
  214.           tryRow = tryRow match {
  215.             case null => if (!(tryPartRow contains E)) tryPartRow else null
  216.             case _ => if (!(tryPartRow contains E)) tryRow && tryPartRow else tryRow
  217.           }
  218.         }
  219.         if (tryRow == null) ErrorRow(row.length) else tryRow
  220.       }
  221.       case _ => row
  222.     }
  223.  
  224.     if (isProblematic) println(s"Returning $ret")
  225.     ret
  226.   }
  227.  
  228.   def fill(ab: ArrayBuffer[Cell], start: Int, end: Int, c: Cell): ArrayBuffer[Cell] = {
  229.     var fillret: ArrayBuffer[Cell] = ab.clone
  230.     if (start > end) ab
  231.     else if (start == end) {
  232.       fillret(start) &= c
  233.     } else {
  234.       for (i <- start to end) {
  235.         fillret(i) &= c
  236.       }
  237.     }
  238.     fillret
  239.   }
  240.  
  241.   def fill(size: Int)(cell: Cell) = Row(ArrayBuffer.fill(size)(cell))
  242. }
  243.  
  244. case class First(cell: Cell) {
  245.   def unapplySeq(row: Row): Option[Seq[Cell]] = {
  246.     if (row.head == cell) Some(row.takeWhile(_ == cell)) else None
  247.   }
  248. }
Add Comment
Please, Sign In to add comment