/* * Shikaku Solver in Copris * by Naoyuki Tamura * http://bach.istc.kobe-u.ac.jp/copris/puzzles/shikaku/ */ package shikaku import jp.kobe_u.copris._ import jp.kobe_u.copris.dsl._ import puzzle._ case class Shikaku(m: Int, n: Int, board: Seq[Seq[String]]) extends BoardPuzzle { def isBlank(cell: Cell) = at(cell) == "-" def sizes(cell: Cell) = { val a = num(cell) for (h <- 1 to a; if a % h == 0) yield (h, a / h) } def show(sol: Seq[(Cell,(Int,Int))]) { val map = ( for { k <- 0 until sol.size ((r,c),(h,w)) = sol(k) i <- r until r+h; j <- c until c+w } yield (i,j) -> k ).toMap def s(i: Int, j: Int) = map.getOrElse((i,j), -1) for (i <- 0 to m) { for (j <- 0 until n) { print("+") if (s(i,j) != s(i-1,j)) print("---") else print(" ") } println("+") if (i < m) { for (j <- 0 until n) { if (s(i,j) != s(i,j-1)) print("|") else print(" ") if (isNumber(i, j)) print("%3d".format(num(i, j))) else print(" ") } println("|") } } } } object Solver extends BoardPuzzleSolver[Shikaku] { val name = "shikaku.Solver" def puzzleFactory(m: Int, n: Int, board: Seq[Seq[String]]) = Shikaku(m, n, board) def define = { for (k <- 0 until puzzle.numberCells.size; cell = puzzle.numberCells(k)) { int('r(k), 0, puzzle.m-1) int('c(k), 0, puzzle.n-1) int('h(k), puzzle.sizes(cell).map(_._1).toSet) int('w(k), puzzle.sizes(cell).map(_._2).toSet) for ((h,w) <- puzzle.sizes(cell)) add(('h(k) === h) <==> ('w(k) === w)) add('r(k) + 'h(k) <= puzzle.m) add('c(k) + 'w(k) <= puzzle.n) val (i,j) = cell add(('r(k) <= i) && ('r(k) + 'h(k) > i)) add(('c(k) <= j) && ('c(k) + 'w(k) > j)) } for (k1 <- 0 until puzzle.numberCells.size; k2 <- k1+1 until puzzle.numberCells.size) add(('r(k1) + 'h(k1) <= 'r(k2)) || ('r(k2) + 'h(k2) <= 'r(k1)) || ('c(k1) + 'w(k1) <= 'c(k2)) || ('c(k2) + 'w(k2) <= 'c(k1))) } def showSolution { val sol = for (k <- 0 until puzzle.numberCells.size) yield ((solution('r(k)),solution('c(k))), (solution('h(k)),solution('w(k)))) if (quiet == 0) { println("Solution = " + sol) println("Size = " + sol.size) puzzle.show(sol) } } }