improved MagicSquareSolver

This commit is contained in:
Louis Heredero 2024-04-30 13:51:57 +02:00
parent 37314cf9db
commit fe28ec45a5
Signed by: HEL
GPG Key ID: 8D83DE470F8544E7

View File

@ -1,10 +1,14 @@
package magic_squares package magic_squares
import scala.collection.mutable.ArrayBuffer
abstract class MagicSquareSolver(initialGrid: Grid) extends Displayable { abstract class MagicSquareSolver(initialGrid: Grid) extends Displayable {
protected var _initial: Grid = initialGrid protected var _initial: Grid = initialGrid
protected var grid: Grid = copy(_initial)
protected val _size: Int = _initial.length protected val _size: Int = _initial.length
protected val SUM: Int = _size * (_size * _size + 1) / 2 protected val SUM: Int = _size * (_size * _size + 1) / 2
protected val DEBUG: Boolean = false protected val DEBUG: Boolean = false
protected val NUMBERS: Array[Int] = Array.range(1, _size * _size + 1)
protected def print(grid: Grid): Unit = { protected def print(grid: Grid): Unit = {
for (y: Int <- 0 until _size) { for (y: Int <- 0 until _size) {
@ -17,53 +21,67 @@ abstract class MagicSquareSolver(initialGrid: Grid) extends Displayable {
} }
def solve(): Unit = { def solve(): Unit = {
val sol: Option[Grid] = solveFrom(_initial, 0, 0) val inGrid: ArrayBuffer[Int] = ArrayBuffer.empty
if (sol.isEmpty) { for (y: Int <- 0 until _size) {
println("No solution") for (x: Int <- 0 until _size) {
} else { if (grid(y)(x) != 0) {
print(sol.get) inGrid.addOne(grid(y)(x))
}
} }
} }
private def solveFrom(grid: Grid, x: Int, y: Int): Option[Grid] = { val solved: Boolean = _solve(inGrid.toArray)
if (DEBUG) println(s"Solving from $x, $y") if (solved) {
if (DEBUG) print(grid)
display(grid) display(grid)
if (!isValid(grid)) { } else {
println("No solution")
}
}
private def _solve(inGrid: Array[Int]): Boolean = {
display(grid)
if (DEBUG) print(grid)
if (!isValid()) {
if (DEBUG) println(" Grid is invalid") if (DEBUG) println(" Grid is invalid")
return None return false
} }
if (y >= _size) {
val (x: Int, y: Int) = getNextEmpty()
if (x == -1) {
if (DEBUG) println(" Found solution") if (DEBUG) println(" Found solution")
return Some(grid) return true
} }
var values: Array[Int] = Array(_initial(y)(x)) val numbers: Array[Int] = NUMBERS.diff(inGrid)
if (values(0) == 0) values = (1 to _size * _size).toArray
if (DEBUG) println(s" Values to test: " + values.mkString("[", ", ", "]"))
val newGrid: Grid = copy(grid) if (DEBUG) println(s" Values to test: " + numbers.mkString("[", ", ", "]"))
var x2: Int = x + 1
var y2: Int = y
if (x2 >= _size) {
x2 -= _size
y2 += 1
}
for (i: Int <- values) { for (n: Int <- numbers) {
if (DEBUG) println(s" Testing $i") if (DEBUG) println(s" Testing $n")
newGrid(y)(x) = i grid(y)(x) = n
val sol: Option[Grid] = solveFrom(newGrid, x2, y2) if (_solve(inGrid.appended(n))) {
if (sol.isDefined) {
if (DEBUG) println(" Found solution, collapsing call stack") if (DEBUG) println(" Found solution, collapsing call stack")
return sol return true
} }
} }
grid(y)(x) = 0
if (DEBUG) println(s" No solution for this configuration") if (DEBUG) println(s" No solution for this configuration")
return None return false
} }
private def isValid(grid: Grid): Boolean = { private def getNextEmpty(): (Int, Int) = {
for (y: Int <- 0 until _size) {
for (x: Int <- 0 until _size) {
if (grid(y)(x) == 0) {
return (x, y)
}
}
}
return (-1, -1)
}
private def isValid(): Boolean = {
val values: Array[Int] = grid.reduce((a, b) => a.concat(b)).filter(_ != 0) val values: Array[Int] = grid.reduce((a, b) => a.concat(b)).filter(_ != 0)
if (values.distinct.length != values.length) return false if (values.distinct.length != values.length) return false
@ -113,7 +131,7 @@ object MagicSquareSolver {
Array(0, 0, 7), Array(0, 0, 7),
Array(0, 9, 0) Array(0, 9, 0)
)) with TextDisplay )) with TextDisplay
solver1.solve() //solver1.solve()
println() println()
/* /*
8,1,6 8,1,6
@ -126,7 +144,7 @@ object MagicSquareSolver {
Array(0, 0, 7), Array(0, 0, 7),
Array(0, 8, 0) Array(0, 8, 0)
)) with TextDisplay )) with TextDisplay
solver2.solve() //solver2.solve()
println() println()
/* /*
no solution no solution