How to resolve the algorithm 15 puzzle solver step by step in the Scala programming language
Published on 12 May 2024 09:40 PM
How to resolve the algorithm 15 puzzle solver step by step in the Scala programming language
Table of Contents
Problem Statement
Your task is to write a program that finds a solution in the fewest moves possible single moves to a random Fifteen Puzzle Game. For this task you will be using the following puzzle:
The output must show the moves' directions, like so: left, left, left, down, right... and so on. There are two solutions, of fifty-two moves: rrrulddluuuldrurdddrullulurrrddldluurddlulurruldrdrd rrruldluuldrurdddluulurrrdlddruldluurddlulurruldrrdd see: Pretty Print of Optimal Solution Finding either one, or both is an acceptable result. Solve the following problem:
Let's start with the solution:
Step by Step solution about How to resolve the algorithm 15 puzzle solver step by step in the Scala programming language
Source code in the scala programming language
import scala.collection.mutable
case class Board(table: Array[Int], r: Int, c: Int, parent: List[String] = List()) {
def cloneSwap(r: Int, c: Int, rr: Int, cc: Int) = {
val cTable = table.clone
// Fancy way to access table(r)(c) in linear array
// Equivalent with cTable(r*4 + c)
cTable(r << 2 | c) = table(rr << 2 | cc)
cTable(rr << 2 | cc) = table(r << 2 | c)
cTable
}
def up() =
if (r > 0) { Some(Board(cloneSwap(r, c, r - 1, c), r - 1, c, "u" :: parent))
} else None
def down() =
if (r < 3) { Some(Board(cloneSwap(r, c, r + 1, c), r + 1, c, "d" :: parent))
} else None
def left() =
if (c > 0) { Some(Board(cloneSwap(r, c, r, c - 1), r, c - 1, "l" :: parent))
} else None
def right() =
if (c < 3) { Some(Board(cloneSwap(r, c, r, c + 1), r, c + 1, "r" :: parent))
} else None
def format: String = {
table.sliding(4, 4).toList.map(_.map(i ⇒ f"$i%4d").mkString).mkString("\n")
}
// Manhattan distance
def heuristic() = {
val posF = Board.finalBoard.positionMap
val posT = positionMap
var res = 0;
for (i ← 0 to 15) {
val (x, y) = posF(i)
val (xx, yy) = posT(i)
res += (Math.abs(x - xx) + Math.abs(y - yy))
}
res
}
def key = table.mkString(",")
def travelled() = parent.length
// Find children/neighbours, flatten eliminates the empty boundaries
def children: List[Board] = List(this.up(), this.down(), this.right(), this.left()).flatten
// Map number to positions
lazy val positionMap: Map[Int, (Int, Int)] = {
val res = mutable.Map[Int, (Int, Int)]()
for (x ← 0 to 3; y ← 0 to 3) {
res(table(x << 2 | y)) = (x, y)
}
res.toMap
}
}
import Board._
object Solver extends App {
def solve(initBoard: Board, wTravel:Int, wHeuristic: Int ) {
// Setup weights for the heuristic, more weight to heuristic faster but longer solution.
def aStar(b: Board) = wHeuristic * b.heuristic() + wTravel * b.travelled()
implicit val ob = new Ordering[Board] {
override def compare(x: Board, y: Board) = {
aStar(y) - aStar(x)
}
}
val start = System.currentTimeMillis()
var found = false
var head = initBoard
val pq: mutable.PriorityQueue[Board] = new mutable.PriorityQueue()
pq.enqueue(head)
val visited = mutable.HashSet[String]()
var explore = 0
while (pq.nonEmpty && !found) {
head = pq.dequeue()
visited.add(head.key)
if (!head.key.equals(finalBoard.key)) {
val newChildren = head.children.filter(child ⇒ !visited.contains(child.key))
visited ++= (newChildren.map(_.key))
pq.enqueue(newChildren: _*)
explore += 1
} else found = true
if (explore % 5000 == 0)
println(s"# $explore: A* ${aStar(head)} g:${head.travelled()} h:${head.heuristic()}")
}
if (found) {
println(s"Exploring $explore states, solution with length ${head.parent.length}.")
println(s"Weighted heuristic used $wHeuristic * heuristic + $wTravel * travel.")
println(initBoard.format)
println(head.parent.mkString.reverse)
}
println("Total time: " + (System.currentTimeMillis() - start) / 1000.0 + " seconds")
}
solve(startEasy, 4, 5)
solve(startHard, 1, 2 )
}
object Board {
val finalBoard = Board(Array(Array(1, 2, 3, 4), Array(5, 6, 7, 8), Array(9, 10, 11, 12), Array(13, 14, 15, 0)).flatten, 3, 3)
val startEasy = Board(Array(Array(15, 14, 1, 6), Array(9, 11, 4, 12), Array(0, 10, 7, 3), Array(13, 8, 5, 2)).flatten, 2, 0)
val startHard = Board(Array(Array(0, 12, 9, 13), Array(15, 11, 10, 14), Array(3, 7, 2, 5), Array(4, 8, 6, 1)).flatten, 0, 0)
}
You may also check:How to resolve the algorithm Find limit of recursion step by step in the Phixmonti programming language
You may also check:How to resolve the algorithm Hello world/Newline omission step by step in the Salmon programming language
You may also check:How to resolve the algorithm Ulam spiral (for primes) step by step in the Mathematica / Wolfram Language programming language
You may also check:How to resolve the algorithm Empty directory step by step in the BBC BASIC programming language
You may also check:How to resolve the algorithm File input/output step by step in the Ada programming language