satchmo-2.9.9.4: examples/Hidoku.hs
-- | Simple Hidoku Benchmark:
-- constraints for an empty board (no hints).
-- argument n: board is n*n.
-- .
-- The encoding here is in a straightforward style, using "one-hot" encoding
-- for numbers, and @Relation.Prop.is_bijection@
-- which contains @exactly-one@ constraints that use binary counters.
-- .
-- For discussion of a many more encoding options,
-- see 4.2 and 4.4 of http://nbn-resolving.de/urn:nbn:de:bsz:14-qucosa-158672
{-# language ScopedTypeVariables #-}
import Prelude hiding ( not, product )
import qualified Prelude
import qualified Satchmo.Relation as R
import Satchmo.Code
import Satchmo.Boolean
import Satchmo.SAT.Mini
import Data.List (inits, tails)
import qualified Data.Array as A
import Control.Monad ( guard, when, forM, foldM, forM_ )
import System.Environment
import Data.Ix ( range)
main :: IO ()
main = do
argv <- getArgs
case argv of
[ ] -> main_with 10
[s] -> main_with $ read s
main_with :: Int -> IO ()
main_with n = do
Just r <- solve $ hidoku n
printA n r
printA :: Int -> A.Array ((Int,Int),Int) Bool -> IO ()
printA n a = putStrLn $ unlines $ do
x <- A.range (1,n)
return $ unwords $ do
y <- A.range (1,n)
let zs = map (\z -> a A.! ((x,y),z)) (A.range (1,n^2))
fill n s = replicate (n - length s) ' ' ++ s
return $ fill 3 $ show $ succ $ length $ takeWhile Prelude.not zs
hidoku :: Int
-> SAT (SAT (A.Array ((Int,Int),Int) Bool))
hidoku n = do
r :: R.Relation (Int,Int) Int <-
R.relation ( ((1,1),1),((n,n),n^2) )
assertM $ R.is_bijection r
forM_ (A.range (1 ,n^2 - 1)) $ \ i -> do
forM_ (A.range ((1,1),(n,n))) $ \ p@(x,y) -> do
assert $ not (r R.!((x,y),i)) : do
(dx,dy) <- A.range ((-1,-1),(1,1))
let q = (x+dx,y+dy)
guard $ p /= q Prelude.&& A.inRange (R.bounds r) (q,i+1)
return $ r R.! ((x+dx,y+dy),i+1)
return $ decode r
assertM action = do x <- action ; assert [x]