-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathQueens.scala
55 lines (45 loc) · 1.46 KB
/
Queens.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package skutek_examples
import skutek.abstraction._
import skutek.std_effects._
object Queens {
case object FxS extends State[Solution]
case object FxC extends Choice
def apply(args: Seq[String]) = {
val boardSize = 8
search(boardSize)
.runWith(FxC.findFirst)
.foreach { solution =>
printSolution(boardSize, solution)
}
}
type Solution = Vector[Placement]
case class Placement(column: Int, row: Int) {
def collidesWith(that: Placement) = {
val x = column - that.column
val y = row - that.row
x == 0 || y == 0 || x == y || x == -y
}
}
def search(boardSize: Int): Solution !! FxC.type = {
(for (row <- 0 until boardSize) yield
for {
solution <- FxS.Get
column <- FxC.Choose(0 until boardSize)
p = Placement(column, row)
if !solution.exists(_.collidesWith(p))
_ <- FxS.Put(solution :+ p)
} yield ()
)
.traverseVoid
.handleWith[FxC.type](FxS.handler(Vector.empty[Placement]).justState)
}
def printSolution(boardSize: Int, ps: Solution) = {
def u(s: String) = Console.UNDERLINED + s + Console.RESET
println(Vector.fill(boardSize)(u(" ")).mkString(" ", " ", ""))
for (p <- ps) {
val line = Vector.fill(boardSize)(u(" ")).updated(p.column, u("\u265B")).mkString("|", "|", "|")
println(s"${boardSize - p.row}${line}")
}
println((0 until boardSize).map(i => ('a'.toInt + i).toChar).mkString(" ", " ", " "))
}
}