import Control.Monad
import qualified Data.IntSet as IntSet
import LogicGrowsOnTrees
import LogicGrowsOnTrees.Parallel.Main
import LogicGrowsOnTrees.Parallel.Adapter.Threads
import LogicGrowsOnTrees.Utils.WordSum
-- Code that counts all the solutions for a given input board size.
nqueensCount 0 = error "board size must be positive"
nqueensCount n =
-- Start with...
go n -- ...n queens left...
0 -- ... at row zero...
-- ... with all columns available ...
(IntSet.fromDistinctAscList [0..fromIntegral n-1])
IntSet.empty -- ... with no occupied negative diagonals...
IntSet.empty -- ... with no occupied positive diagonals.
where
-- We have placed the last queen, so this is a solution!
go 0 _ _ _ _ = return (WordSum 1)
-- We are still placing queens.
go n
row
available_columns
occupied_negative_diagonals
occupied_positive_diagonals
= do
-- Pick one of the available columns.
column <- allFrom $ IntSet.toList available_columns
-- See if this spot conflicts with another queen on the negative diagonal.
let negative_diagonal = row + column
guard $ IntSet.notMember negative_diagonal occupied_negative_diagonals
-- See if this spot conflicts with another queen on the positive diagonal.
let positive_diagonal = row - column
guard $ IntSet.notMember positive_diagonal occupied_positive_diagonals
-- This spot is good! Place a queen here and move on to the next row.
go (n-1)
(row+1)
(IntSet.delete column available_columns)
(IntSet.insert negative_diagonal occupied_negative_diagonals)
(IntSet.insert positive_diagonal occupied_positive_diagonals)
main =
-- Explore the tree generated (implicitly) by nqueensCount in parallel.
simpleMainForExploreTree
-- Use threads for parallelism.
driver
-- Function that processes the result of the run.
(\(RunOutcome _ termination_reason) -> do
case termination_reason of
Aborted _ -> error "search aborted"
Completed (WordSum count) -> putStrLn $ "found " ++ show count ++ " solutions"
Failure _ message -> error $ "error: " ++ message
)
-- The logic program that generates the tree to explore.
(nqueensCount 10)