Created
August 26, 2012 10:38
-
-
Save AitorATuin/3477138 to your computer and use it in GitHub Desktop.
Eight Queens in scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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