1
+ package gopher .monadexample
2
+ import cps .*
3
+ import gopher .*
4
+ import munit .*
5
+
6
+ import scala .concurrent .*
7
+ import scala .concurrent .duration .*
8
+ import scala .collection .SortedSet
9
+
10
+ import cps .monads .FutureAsyncMonad
11
+ // import gopher.monads.given
12
+ import gopher .monads .ReadChannelCpsMonad
13
+
14
+
15
+ class QueensSuite extends FunSuite {
16
+
17
+ import scala .concurrent .ExecutionContext .Implicits .global
18
+ given Gopher [Future ] = SharedGopherAPI .apply[Future ]()
19
+
20
+ case class State (
21
+ busyRows: Set [Int ],
22
+ busyColumns: Set [Int ],
23
+ busyDiagonals: Set [Int ],
24
+ queens : Set [(Int ,Int )]
25
+ );
26
+
27
+ val N = 8
28
+
29
+ def putQueen (state: State ): ReadChannel [Future ,State ] =
30
+ val ch = makeChannel[State ]()
31
+ async[Future ] {
32
+ for {
33
+ i <- 0 until N if ! state.busyRows.contains(i)
34
+ j <- 0 until N if ! state.busyColumns.contains(j) &&
35
+ ! (state.busyDiagonals.contains(i- j))
36
+ } {
37
+ val newPos = (i,j)
38
+ val nState = state.copy( busyRows = state.busyRows + i,
39
+ busyColumns = state.busyColumns + j,
40
+ busyDiagonals = state.busyDiagonals + (i- j),
41
+ queens = state.queens + newPos )
42
+ ch.write(nState)
43
+ }
44
+ ch.close()
45
+ }
46
+ ch
47
+
48
+ def solutions (state : State ): ReadChannel [Future ,State ] =
49
+ async[[X ] =>> ReadChannel [Future ,X ]] {
50
+ if (state.queens.size < 8 ) then
51
+ val nextState = await(putQueen(state))
52
+ await(solutions(nextState))
53
+ else
54
+ state
55
+ }
56
+
57
+ val emptyState = State (Set .empty, Set .empty, Set .empty, Set .empty)
58
+
59
+ test(" first solution for 8 queens problem" ) {
60
+ async[Future ] {
61
+ val r = solutions(emptyState).take(1 )
62
+ assert(! r.isEmpty)
63
+ println(r.head.queens)
64
+ }
65
+ }
66
+
67
+
68
+
69
+ }
0 commit comments