/* * Hakyuu Solver in Copris * by Naoyuki Tamura * http://bach.istc.kobe-u.ac.jp/copris/puzzles/hakyuu/ */ package hakyuu import jp.kobe_u.copris._ import jp.kobe_u.copris.dsl._ import puzzle._ case class Hakyuu(m: Int, n: Int, board: Seq[Seq[String]]) extends BoardPuzzle { def areaName(cell: Cell) = at(cell).split(":")(0) val areaNames = cells.map(areaName).toSet val areaCells = areaNames.map(name => name -> cells.filter(cell => areaName(cell) == name).toSet).toMap def isHint(cell: Cell) = at(cell).split(":").size >= 2 def hint(cell: Cell) = at(cell).split(":")(1).toInt def show(sol: Seq[Seq[Int]]) { for (i <- 0 until m) { for (j <- 0 until n) print("%2d".format(sol(i)(j))) println } } } object Solver extends BoardPuzzleSolver[Hakyuu] { val name = "hakyuu.Solver" def puzzleFactory(m: Int, n: Int, board: Seq[Seq[String]]) = Hakyuu(m, n, board) def define = { for (cell <- puzzle.cells) if (puzzle.isHint(cell)) int('x(cell), puzzle.hint(cell)) else int('x(cell), 1, puzzle.areaCells(puzzle.areaName(cell)).size) for (name <- puzzle.areaNames) add(Alldifferent(puzzle.areaCells(name).map('x(_)))) for (cell <- puzzle.cells) { val values = if (puzzle.isHint(cell)) Seq(puzzle.hint(cell)) else 1 to puzzle.areaCells(puzzle.areaName(cell)).size for (x <- values; (di,dj) <- puzzle.dijs; k <- 1 to x) { val cell1 = puzzle.move(cell, (k*di,k*dj)) if (puzzle.isCell(cell1)) add(('x(cell) =/= x) || ('x(cell1) =/= x)) } } } def showSolution { val sol = for (i <- 0 until puzzle.m) yield (0 until puzzle.n).map(j => solution('x((i,j)))) if (quiet == 0) { println("Solution = " + sol) println("Size = " + sol.size) puzzle.show(sol) } } }