/* * Kakuro Solver in Copris * by Naoyuki Tamura * http://bach.istc.kobe-u.ac.jp/copris/puzzles/kakuro/ */ package kakuro import jp.kobe_u.copris._ import jp.kobe_u.copris.dsl._ import puzzle._ case class Kakuro(m: Int, n: Int, board: Seq[Seq[String]]) extends BoardPuzzle { def isBlank(cell: Cell) = at(cell) == "-" def isHint(cell: Cell) = at(cell).matches("""\d+\\\d+""") def hint(cell: Cell) = { val s = at(cell).split("""\\""").map(_.toInt) (s(0),s(1)) } def block(cell: Cell, dij: Cell): Seq[Cell] = if (! isCell(cell) || ! isBlank(cell)) Seq.empty else cell +: block(move(cell, dij), dij) val blocks: Set[(Int,Seq[Cell])] = { val rowBlocks = for (cell <- cells; if isHint(cell); (rsum,csum) = hint(cell); if rsum > 0) yield (rsum, block(move(cell, (1,0)), (1,0))) val colBlocks = for (cell <- cells; if isHint(cell); (rsum,csum) = hint(cell); if csum > 0) yield (csum, block(move(cell, (0,1)), (0,1))) rowBlocks.toSet ++ colBlocks.toSet } def show(sol: Map[Cell,Int]) { for (i <- 0 until m) { for (j <- 0 until n; cell = (i,j)) { if (isBlank(cell)) print(" " + sol(cell) + " ") else { val (rsum,csum) = hint(cell) print("[%2d\\%-2d]".format(rsum, csum)) } } println } } } object Solver extends BoardPuzzleSolver[Kakuro] { val name = "kakuro.Solver" def puzzleFactory(m: Int, n: Int, board: Seq[Seq[String]]) = Kakuro(m, n, board) def define = { for (cell <- puzzle.cells; if puzzle.isBlank(cell)) int('x(cell), 1, 9) for ((sum,block) <- puzzle.blocks) { val xs = block.map(cell => 'x(cell)) add(Add(xs) === sum) add(Alldifferent(xs)) } } def showSolution { val sol = { for (cell <- puzzle.cells; if puzzle.isBlank(cell)) yield cell -> solution('x(cell)) }.toMap if (quiet == 0) { println("Solution = " + sol) println("Size = " + sol.size) puzzle.show(sol) } } }