- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
OO n-queens; comments?
Mon, 2009-03-09, 20:41
As an exercise, I decided to write the n-queens problem (without
looking at the solution :-) ), but using some OO in there to make
things (I believe) a little clearer. I'd be curious as to what people
thought--is the OO solution really easier to understand, or am I just
thinking too much in OO?
Oh, it has a really crude printout facility, if you actually run it....
Thanks,
Ken
-----------------
package nqueensPackage
// A position is the position of a single queen.
case class Position(row:Int, col:Int) {
// Is this position safe from being in check by a queen at
position p?
def isSafeFrom(p:Position) = {
(p.row != row) && (p.col != col) && ((p.col-col).abs !=
(p.row-row).abs)
}
}
// A layout is a layout of queens, none in check with each other.
class Layout(var positions:List[Position]) {
def this() = this(List())
//Is this layout safe for placement of a queen at position p?
def isSafeFor(p:Position) = {
positions.forall(p.isSafeFrom _)
}
// Return a new layout with a queen added at the given position.
def add(p:Position) = new Layout(p::positions)
override def toString:String = {
var sorted = positions.sort((x, y) => x.row < y.row)
var rowStrings = for (s <- sorted) yield "| "*(s.col-1) + "|
*" + "| " *(positions.length-s.col+1)
rowStrings = "\n------" :: rowStrings
rowStrings.mkString("\n")
}
}
object nqueens {
// Place N queens on an NxN board
def placeN(dimension:Int) = {
// divide and conquer. Row is the row on which we are
// placing a queen.
def place(row:Int):List[Layout] = {
// If this is row 0 (of a 0x0 board), the puzzle is
solved by
// a null Layout
if (row == 0) List(new Layout())
// otherwise, row >= 1; place everything safely in rows
0...row-1,
// for each column in the current row, try to place a
queen, and if
// successful, yield the result for inclusion in the
results.
else for(
layout <- place(row - 1);
col <- 1 to dimension;
p = Position(row, col);
if layout.isSafeFor(p)
)
yield layout.add(p)
}
// Start the main 'place' function with the dimension of the
board.
place(dimension)
}
def main(args: Array[String]) = {
println("Hello, world!")
println(placeN(6).mkString)
}
}