magic square solver
This commit is contained in:
parent
124b4c7a33
commit
8e9567e1a2
146
src/magic_squares/MagicSquareSolver.scala
Normal file
146
src/magic_squares/MagicSquareSolver.scala
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
package magic_squares
|
||||||
|
|
||||||
|
class MagicSquareSolver(initialGrid: Grid) {
|
||||||
|
protected var _initial: Grid = initialGrid
|
||||||
|
protected val _size: Int = _initial.length
|
||||||
|
protected val SUM: Int = 15
|
||||||
|
protected val DEBUG: Boolean = false
|
||||||
|
|
||||||
|
protected def print(grid: Grid): Unit = {
|
||||||
|
for (y: Int <- 0 until _size) {
|
||||||
|
println(grid(y).mkString(","))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected def copy(grid: Grid): Grid = {
|
||||||
|
return grid.map(_.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
def solve(): Unit = {
|
||||||
|
val sol: Option[Grid] = solveFrom(_initial, 0, 0)
|
||||||
|
if (sol.isEmpty) {
|
||||||
|
println("No solution")
|
||||||
|
} else {
|
||||||
|
print(sol.get)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def solveFrom(grid: Grid, x: Int, y: Int): Option[Grid] = {
|
||||||
|
if (DEBUG) println(s"Solving from $x, $y")
|
||||||
|
if (DEBUG) print(grid)
|
||||||
|
if (!isValid(grid)) {
|
||||||
|
if (DEBUG) println(" Grid is invalid")
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
if (y >= _size) {
|
||||||
|
if (DEBUG) println(" Found solution")
|
||||||
|
return Some(grid)
|
||||||
|
}
|
||||||
|
var values: Array[Int] = Array(_initial(y)(x))
|
||||||
|
if (values(0) == 0) values = (1 to 9).toArray
|
||||||
|
if (DEBUG) println(s" Values to test: " + values.mkString("[", ", ", "]"))
|
||||||
|
|
||||||
|
val newGrid: Grid = copy(grid)
|
||||||
|
var x2: Int = x + 1
|
||||||
|
var y2: Int = y
|
||||||
|
if (x2 >= _size) {
|
||||||
|
x2 -= _size
|
||||||
|
y2 += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i: Int <- values) {
|
||||||
|
if (DEBUG) println(s" Testing $i")
|
||||||
|
newGrid(y)(x) = i
|
||||||
|
val sol: Option[Grid] = solveFrom(newGrid, x2, y2)
|
||||||
|
if (sol.isDefined) {
|
||||||
|
if (DEBUG) println(" Found solution, collapsing call stack")
|
||||||
|
return sol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG) println(s" No solution for this configuration")
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
|
||||||
|
private def isValid(grid: Grid): Boolean = {
|
||||||
|
val values: Array[Int] = grid.reduce((a, b) => a.concat(b)).filter(_ != 0)
|
||||||
|
if (values.distinct.length != values.length) return false
|
||||||
|
|
||||||
|
val diag1: Array[Int] = new Array(_size)
|
||||||
|
val diag2: Array[Int] = new Array(_size)
|
||||||
|
for (i: Int <- 0 until _size) {
|
||||||
|
val row: Array[Int] = grid(i)
|
||||||
|
val col: Array[Int] = grid.map(_(i))
|
||||||
|
diag1(i) = row(i)
|
||||||
|
diag2(i) = col(_size - i - 1)
|
||||||
|
|
||||||
|
if (!isLineValid(row)) {
|
||||||
|
if (DEBUG) println(s" -> row $i is invalid: " + row.mkString("[", ", ", "]"))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!isLineValid(col)) {
|
||||||
|
if (DEBUG) println(s" -> column $i is invalid: " + col.mkString("[", ", ", "]"))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isLineValid(diag1)) {
|
||||||
|
if (DEBUG) println(s" -> diag1 is invalid: " + diag1.mkString("[", ", ", "]"))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!isLineValid(diag2)) {
|
||||||
|
if (DEBUG) println(s" -> diag2 is invalid: " + diag2.mkString("[", ", ", "]"))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private def isLineValid(line: Array[Int]): Boolean = {
|
||||||
|
val sum: Int = line.sum
|
||||||
|
if (line.contains(0)) {
|
||||||
|
if (sum > SUM) return false
|
||||||
|
} else if (sum != SUM) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object MagicSquareSolver {
|
||||||
|
def main(args: Array[String]): Unit = {
|
||||||
|
val solver1: MagicSquareSolver = new MagicSquareSolver(Array(
|
||||||
|
Array(8, 0, 0),
|
||||||
|
Array(0, 0, 7),
|
||||||
|
Array(0, 9, 0)
|
||||||
|
))
|
||||||
|
solver1.solve()
|
||||||
|
println()
|
||||||
|
/*
|
||||||
|
8,1,6
|
||||||
|
3,5,7
|
||||||
|
4,9,2
|
||||||
|
*/
|
||||||
|
|
||||||
|
val solver2: MagicSquareSolver = new MagicSquareSolver(Array(
|
||||||
|
Array(9, 0, 0),
|
||||||
|
Array(0, 0, 7),
|
||||||
|
Array(0, 8, 0)
|
||||||
|
))
|
||||||
|
solver2.solve()
|
||||||
|
println()
|
||||||
|
/*
|
||||||
|
no solution
|
||||||
|
*/
|
||||||
|
|
||||||
|
val solver3: MagicSquareSolver = new MagicSquareSolver(Array(
|
||||||
|
Array(0, 0, 2),
|
||||||
|
Array(0, 5, 7),
|
||||||
|
Array(0, 0, 0)
|
||||||
|
))
|
||||||
|
solver3.solve()
|
||||||
|
/*
|
||||||
|
4,9,2
|
||||||
|
3,5,7
|
||||||
|
8,1,6
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
3
src/magic_squares/package.scala
Normal file
3
src/magic_squares/package.scala
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
package object magic_squares {
|
||||||
|
type Grid = Array[Array[Int]]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user