/* * Sudoku Solver in Copris * by Naoyuki Tamura * http://bach.istc.kobe-u.ac.jp/copris/puzzles/sudoku/ */ package sudoku import jp.kobe_u.copris._ import jp.kobe_u.copris.dsl._ import puzzle._ case class Sudoku(m: Int, n: Int, dm: Int, dn: Int, board: Seq[Seq[String]]) extends BoardPuzzle { require(m == n && m == dm * dn) def show(sol: Seq[Seq[Int]]) { for (i <- 0 until m) { for (j <- 0 until n) print("%3d".format(sol(i)(j))) println } } } object Solver extends BoardPuzzleSolver[Sudoku] { val name = "sudoku.Solver" def puzzleFactory(m: Int, n: Int, dm: Int, dn: Int, board: Seq[Seq[String]]) = Sudoku(m, n, dm, dn, board) override def puzzleFactory(m: Int, n: Int, board: Seq[Seq[String]]) = { val dm = math.sqrt(m).toInt require(m == n && m == dm * dm) puzzleFactory(m, n, dm, dm, board) } override def parse(source: scala.io.Source) = { val lines = source.getLines.map(_.trim).filter(! _.startsWith(";")) val ms = lines.next.split("\\s+").map(_.toInt) val m = ms(0) val dm = if (ms.size >= 2) ms(1) else math.sqrt(m).toInt val ns = lines.next.split("\\s+").map(_.toInt) val n = ns(0) val dn = if (ns.size >= 2) ns(1) else math.sqrt(n).toInt val board = for (i <- 0 until m; s = lines.next) yield s.split("\\s+").toSeq source.close puzzleFactory(m, n, dm, dn, board) } def define = { for (cell <- puzzle.cells) if (puzzle.isNumber(cell)) int('x(cell), puzzle.num(cell)) else int('x(cell), 1, puzzle.m) for (i <- 0 until puzzle.m) add(Alldifferent((0 until puzzle.n).map(j => 'x((i,j))))) for (j <- 0 until puzzle.n) add(Alldifferent((0 until puzzle.m).map(i => 'x((i,j))))) for (i <- 0 until puzzle.m by puzzle.dm; j <- 0 until puzzle.n by puzzle.dn) { val xs = for (di <- 0 until puzzle.dm; dj <- 0 until puzzle.dn) yield 'x((i+di,j+dj)) add(Alldifferent(xs)) } } 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) } } }