Skip to content

Instantly share code, notes, and snippets.

@AitorATuin
Created August 26, 2012 10:38
Show Gist options
  • Save AitorATuin/3477138 to your computer and use it in GitHub Desktop.
Save AitorATuin/3477138 to your computer and use it in GitHub Desktop.
Eight Queens in scala
package org.noisesOfHill.exercises.EightQueens
import scalaz._
import Scalaz._
/**
* User: AitorATuin
* Date: 13/06/12
* Time: 19:56
* Little program to solve the epic problem of the Eight Queens.
* first8QueensSolution founds one solution
* all8QueensSolution encuentra found all possible solutions (including permutations)
*/
object EightQueens {
/*
* This returns a String representing a board with a solution.
* Each square is represented with character '.' and queens with char 'X'
*/
private def genBoard(queens:List[Int], board:List[String]):List[String]= queens match {
case Nil => board
case x :: xs => {
val b = ("%s%s%s".format("." * x,"X","." * (7 - x)).toList.mkString(" "))
genBoard(xs, b :: board)
}
}
/*
* Function that returns possible moves for the next row in a board configuration.
*/
private def posibleMoves(currentMoves:List[Int]) = {
val notPosibleMoves = ((currentMoves zip (1 to (currentMoves.length))) map {
case (queen, offset) =>
List(queen - offset, queen, queen + offset) }
).flatten.filter(_ >= 0).toSet
Stream((0 to 7).filterNot((i) => notPosibleMoves.contains(i)).toList: _*)
}
/*
* Recursive function that returns the first found solution.
*/
private def _first8QueensSolution(path:List[Int], forNQueens:Int):Option[List[Int]] =
path.length match {
case n if n == forNQueens => path.some
case _ => {
var solution:Option[List[Int]] = List().some
posibleMoves(path).find { c =>
solution = _first8QueensSolution(c :: path, forNQueens)
solution != None
} match {
case Some(x) => solution
case None => None
}
}
}
/*
* Recursive function that returns all the solutions
*/
private def _all8QueensSolutions(path:List[Int], forNQueens:Int):Option[List[Int]] =
path.length match {
case n if n == forNQueens => path.some
case _ => posibleMoves(path) match {
case Stream.Empty => None
case s => s.map(c =>
_all8QueensSolutions(c :: path, forNQueens)).flatten.toList.flatten.some
}
}
/*
* Interface for both recursive functions.
*/
def first8QueensSolution:Option[List[Int]] = _first8QueensSolution(List(), 8)
def all8QueensSolutions:Option[List[List[Int]]] =
_all8QueensSolutions(List(), 8).some(_.grouped(8).toList.some).none(none)
/*
* Interface to draw the board with a solution
*/
def toBoard(s:Option[List[Int]]) = s.
some(genBoard(_, List()).mkString("\n")).
none("NO SOLUTIONS")
def main(args:Array[String]) = {
println("First found solution:")
println(toBoard(first8QueensSolution))
println("All solutions:")
println(all8QueensSolutions)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment