/* * Akari Solver in Copris * by Naoyuki Tamura * http://bach.istc.kobe-u.ac.jp/copris/puzzles/akari/ */ package akari import jp.kobe_u.copris._ import jp.kobe_u.copris.dsl._ import puzzle._ case class Akari(m: Int, n: Int, board: Seq[Seq[String]]) extends BoardPuzzle { def isBlank(cell: Cell) = at(cell) == "-" def isBlack(cell: Cell) = at(cell) == "x" val lines = { def seq(cell: Cell, dij: Cell): Seq[Cell] = if (! isCell(cell) || ! isBlank(cell)) Seq.empty else cell +: seq(move(cell, dij), dij) val vLines = for ((i,j) <- cells; if ! isCell((i-1,j)) || ! isBlank((i-1,j))) yield seq((i,j), (1,0)).toSet val hLines = for ((i,j) <- cells; if ! isCell((i,j-1)) || ! isBlank((i,j-1))) yield seq((i,j), (0,1)).toSet vLines ++ hLines } def show(sol: Set[Cell]) { for (i <- 0 until m) { for (j <- 0 until n) { val cell = (i,j) if (sol.contains(cell)) print(" @") else print(" " + at(cell)) } println } } } object Solver extends BoardPuzzleSolver[Akari] { val name = "akari.Solver" def puzzleFactory(m: Int, n: Int, board: Seq[Seq[String]]) = Akari(m, n, board) def define = { for (cell <- puzzle.cells; if puzzle.isBlank(cell)) int('x(cell), 0, 1) for ((cell) <- puzzle.cells; if puzzle.isNumber(cell)) { val xs = puzzle.adjCells(cell, puzzle.isBlank).map('x(_)) add(Add(xs) === puzzle.num(cell)) } val lines = puzzle.lines for (k <- 0 until lines.size) { int('l(k), 0, 1) add('l(k) === Add(lines(k).map(cell => 'x(cell)))) } for (cell <- puzzle.cells; if puzzle.isBlank(cell)) { val ks = (0 until lines.size).filter(k => lines(k).contains(cell)) add(Or(ks.map(k => 'l(k) === 1))) } } def showSolution { // Set of light cell positions val sol = for (cell <- puzzle.cells.toSet; if puzzle.isBlank(cell) && solution('x(cell)) > 0) yield cell if (quiet == 0) { println("Solution = " + sol) println("Size = " + sol.size) puzzle.show(sol) } } }