packages feed

satchmo-2.9.9.4: examples/Langford.hs

-- | The Langford Sequence Problem
-- http://www.csplib.org/Problems/prob024/

{-# language ScopedTypeVariables #-}

import Prelude hiding ( not, product, and, or )
import qualified Prelude

import qualified Satchmo.Relation as R
import Satchmo.Code
import Satchmo.Boolean
import qualified Satchmo.Counting as C

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)
import Data.List ( sort )

main :: IO ()
main = do
    argv <- getArgs
    case argv of
      [ ] -> main_with 12
      [s] -> main_with $ read s

main_with :: Int -> IO ()
main_with n = do
    Just a <- solve $ langford n
    let  xs = do
           let ((u,l),(o,r)) = A.bounds a
           y <- A.range (l,r) 
           let zs = map (\x -> a A.! (x,y) ) (A.range(u,o))
           return $ length $ takeWhile Prelude.not zs
    print $ map (\x -> 1 + div x 2) xs

langford :: Int
       -> SAT (SAT (A.Array (Int,Int) Bool))
langford k = do
  --   r(x,y) <=> number (div x 2) is at position y
  r :: R.Relation Int Int <-
    R.relation ((2,1),(2*k+1,2*k))
  assertM $ R.is_bijection r
  false <- constant False
  forM_ [ 1 .. k ] $ \ x -> do
    forM_ [ 1 .. 2*k ] $ \ y -> do
      assert [ not $ r R.! (2*x+0 , y)
             , if x+y+1<=2*k then r R.! (2*x+1, x+y+1) else false
             ]
      assert [ not $ r R.! (2*x+1, y)
             , if y-x-1 >= 1 then r R.! (2*x, y-x-1) else false
             ]
  return $ decode r

assertM action = do x <- action ; assert [x]
fromfunc bnd f = R.build bnd $ do i <- A.range bnd ; return (i, f i )