8-QUEEN

まぁ8に限らないんですが、コンパイル時に数字が決めうちなのが悲しいです。
それと、何も考えずに実装しているので(たぶん)効率が悪いです。

import Control.Monad.State
import Data.List
type Coord = (Int, Int)
type Queens = [Coord]

-- solver
num = 16     -- borad size
putQueen :: Int -> StateT Queens [] ()
putQueen y | y == num  = return ()
           | otherwise =
    do queens <- get
       let usedxs = map fst queens
       newpos <- lift [ (newx,y) | newx <- [0..num-1] ?? usedxs ]
       guard $ notElem newpos $ concatMap slant queens
       put $ newpos:queens
       putQueen $ y+1
slant :: Coord -> [Coord]
slant (x,y) =
    (x,y) : zip upx upy ++ zip upx downy ++ zip downx upy ++ zip downx downy
    where (upx, downx) = ([x+1..num-1], [x-1,x-2..0])
          (upy, downy) = ([y+1..num-1], [y-1,y-2..0])
-- print the chess-board
toStr = foldl f (replicate num $ replicate num '*')
    where f l (x,y) = updateList (updateList 'Q' (l!!y) x) l y
updateList e l n = let (h, t:ts) = splitAt n l in h ++ e : ts
-- solve and print
solve = mapM_ putStrLn $ toStr . head $ execStateT (putQueen 0) []
main = solve
% time ./8queen
Q***************
**Q*************
****Q***********
*Q**************
************Q***
********Q*******
*************Q**
***********Q****
**************Q*
*****Q**********
***************Q
******Q*********
***Q************
**********Q*****
*******Q********
*********Q******
./8queen  1.92s user 0.03s system 99% cpu 1.952 total
%