{-# OPTIONS_GHC -Wall -Werror -Wno-incomplete-uni-patterns #-}
module Documentation.SBV.Examples.Puzzles.Birthday where
import Data.SBV
type Month = SWord8
type Day = SWord8
may, june, july, august :: SWord8
[SWord8
may, SWord8
june, SWord8
july, SWord8
august] = [SWord8
5, SWord8
6, SWord8
7, SWord8
8]
valid :: Month -> Day -> SBool
valid :: SWord8 -> SWord8 -> SBool
valid SWord8
month SWord8
day = (SWord8
month, SWord8
day) (SWord8, SWord8) -> [(SWord8, SWord8)] -> SBool
forall a. EqSymbolic a => a -> [a] -> SBool
`sElem` [(SWord8, SWord8)]
candidates
where candidates :: [(Month, Day)]
candidates :: [(SWord8, SWord8)]
candidates = [ ( SWord8
may, SWord8
15), ( SWord8
may, SWord8
16), ( SWord8
may, SWord8
19)
, ( SWord8
june, SWord8
17), ( SWord8
june, SWord8
18)
, ( SWord8
july, SWord8
14), ( SWord8
july, SWord8
16)
, (SWord8
august, SWord8
14), (SWord8
august, SWord8
15), (SWord8
august, SWord8
17)
]
existsDay :: (Day -> SBool) -> SBool
existsDay :: (SWord8 -> SBool) -> SBool
existsDay SWord8 -> SBool
f = (Word8 -> SBool) -> [Word8] -> SBool
forall a. (a -> SBool) -> [a] -> SBool
sAny (SWord8 -> SBool
f (SWord8 -> SBool) -> (Word8 -> SWord8) -> Word8 -> SBool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> SWord8
forall a. SymVal a => a -> SBV a
literal) [Word8
14 .. Word8
19]
forallDay :: (Day -> SBool) -> SBool
forallDay :: (SWord8 -> SBool) -> SBool
forallDay SWord8 -> SBool
f = (Word8 -> SBool) -> [Word8] -> SBool
forall a. (a -> SBool) -> [a] -> SBool
sAll (SWord8 -> SBool
f (SWord8 -> SBool) -> (Word8 -> SWord8) -> Word8 -> SBool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> SWord8
forall a. SymVal a => a -> SBV a
literal) [Word8
14 .. Word8
19]
existsMonth :: (Month -> SBool) -> SBool
existsMonth :: (SWord8 -> SBool) -> SBool
existsMonth SWord8 -> SBool
f = (SWord8 -> SBool) -> [SWord8] -> SBool
forall a. (a -> SBool) -> [a] -> SBool
sAny SWord8 -> SBool
f [SWord8
may .. SWord8
august]
forallMonth :: (Month -> SBool) -> SBool
forallMonth :: (SWord8 -> SBool) -> SBool
forallMonth SWord8 -> SBool
f = (SWord8 -> SBool) -> [SWord8] -> SBool
forall a. (a -> SBool) -> [a] -> SBool
sAll SWord8 -> SBool
f [SWord8
may .. SWord8
august]
puzzle :: Predicate
puzzle :: Predicate
puzzle = do SWord8
birthDay <- String -> Symbolic SWord8
forall a. SymVal a => String -> Symbolic (SBV a)
sbvExists String
"birthDay"
SWord8
birthMonth <- String -> Symbolic SWord8
forall a. SymVal a => String -> Symbolic (SBV a)
sbvExists String
"birthMonth"
let a1 :: SWord8 -> SBool
a1 SWord8
m = (SWord8 -> SBool) -> SBool
existsDay ((SWord8 -> SBool) -> SBool) -> (SWord8 -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \SWord8
d1 -> (SWord8 -> SBool) -> SBool
existsDay ((SWord8 -> SBool) -> SBool) -> (SWord8 -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \SWord8
d2 ->
SWord8
d1 SWord8 -> SWord8 -> SBool
forall a. EqSymbolic a => a -> a -> SBool
./= SWord8
d2 SBool -> SBool -> SBool
.&& SWord8 -> SWord8 -> SBool
valid SWord8
m SWord8
d1 SBool -> SBool -> SBool
.&& SWord8 -> SWord8 -> SBool
valid SWord8
m SWord8
d2
let a2 :: SWord8 -> SBool
a2 SWord8
m = (SWord8 -> SBool) -> SBool
forallDay ((SWord8 -> SBool) -> SBool) -> (SWord8 -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \SWord8
d -> SWord8 -> SWord8 -> SBool
valid SWord8
m SWord8
d SBool -> SBool -> SBool
.=>
(SWord8 -> SBool) -> SBool
existsMonth (\SWord8
m1 -> (SWord8 -> SBool) -> SBool
existsMonth ((SWord8 -> SBool) -> SBool) -> (SWord8 -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \SWord8
m2 ->
SWord8
m1 SWord8 -> SWord8 -> SBool
forall a. EqSymbolic a => a -> a -> SBool
./= SWord8
m2 SBool -> SBool -> SBool
.&& SWord8 -> SWord8 -> SBool
valid SWord8
m1 SWord8
d SBool -> SBool -> SBool
.&& SWord8 -> SWord8 -> SBool
valid SWord8
m2 SWord8
d)
let b1 :: SWord8 -> SBool
b1 SWord8
d = (SWord8 -> SBool) -> SBool
existsMonth ((SWord8 -> SBool) -> SBool) -> (SWord8 -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \SWord8
m1 -> (SWord8 -> SBool) -> SBool
existsMonth ((SWord8 -> SBool) -> SBool) -> (SWord8 -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \SWord8
m2 ->
SWord8
m1 SWord8 -> SWord8 -> SBool
forall a. EqSymbolic a => a -> a -> SBool
./= SWord8
m2 SBool -> SBool -> SBool
.&& SWord8 -> SWord8 -> SBool
valid SWord8
m1 SWord8
d SBool -> SBool -> SBool
.&& SWord8 -> SWord8 -> SBool
valid SWord8
m2 SWord8
d
let b2p :: SWord8 -> SWord8 -> SBool
b2p SWord8
m SWord8
d = SWord8 -> SWord8 -> SBool
valid SWord8
m SWord8
d SBool -> SBool -> SBool
.&& SWord8 -> SBool
a1 SWord8
m SBool -> SBool -> SBool
.&& SWord8 -> SBool
a2 SWord8
m
b2 :: SWord8 -> SBool
b2 SWord8
d = (SWord8 -> SBool) -> SBool
forallMonth ((SWord8 -> SBool) -> SBool) -> (SWord8 -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \SWord8
m1 -> (SWord8 -> SBool) -> SBool
forallMonth ((SWord8 -> SBool) -> SBool) -> (SWord8 -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \SWord8
m2 ->
(SWord8 -> SWord8 -> SBool
b2p SWord8
m1 SWord8
d SBool -> SBool -> SBool
.&& SWord8 -> SWord8 -> SBool
b2p SWord8
m2 SWord8
d) SBool -> SBool -> SBool
.=> SWord8
m1 SWord8 -> SWord8 -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SWord8
m2
let a3p :: SWord8 -> SWord8 -> SBool
a3p SWord8
m SWord8
d = SWord8 -> SWord8 -> SBool
valid SWord8
m SWord8
d SBool -> SBool -> SBool
.&& SWord8 -> SBool
a1 SWord8
m SBool -> SBool -> SBool
.&& SWord8 -> SBool
a2 SWord8
m SBool -> SBool -> SBool
.&& SWord8 -> SBool
b1 SWord8
d SBool -> SBool -> SBool
.&& SWord8 -> SBool
b2 SWord8
d
a3 :: SWord8 -> SBool
a3 SWord8
m = (SWord8 -> SBool) -> SBool
forallDay ((SWord8 -> SBool) -> SBool) -> (SWord8 -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \SWord8
d1 -> (SWord8 -> SBool) -> SBool
forallDay ((SWord8 -> SBool) -> SBool) -> (SWord8 -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \SWord8
d2 ->
(SWord8 -> SWord8 -> SBool
a3p SWord8
m SWord8
d1 SBool -> SBool -> SBool
.&& SWord8 -> SWord8 -> SBool
a3p SWord8
m SWord8
d2) SBool -> SBool -> SBool
.=> SWord8
d1 SWord8 -> SWord8 -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SWord8
d2
SBool -> SymbolicT IO ()
forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain (SBool -> SymbolicT IO ()) -> SBool -> SymbolicT IO ()
forall a b. (a -> b) -> a -> b
$ SWord8 -> SBool
a1 SWord8
birthMonth
SBool -> SymbolicT IO ()
forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain (SBool -> SymbolicT IO ()) -> SBool -> SymbolicT IO ()
forall a b. (a -> b) -> a -> b
$ SWord8 -> SBool
a2 SWord8
birthMonth
SBool -> SymbolicT IO ()
forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain (SBool -> SymbolicT IO ()) -> SBool -> SymbolicT IO ()
forall a b. (a -> b) -> a -> b
$ SWord8 -> SBool
b1 SWord8
birthDay
SBool -> SymbolicT IO ()
forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain (SBool -> SymbolicT IO ()) -> SBool -> SymbolicT IO ()
forall a b. (a -> b) -> a -> b
$ SWord8 -> SBool
b2 SWord8
birthDay
SBool -> SymbolicT IO ()
forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain (SBool -> SymbolicT IO ()) -> SBool -> SymbolicT IO ()
forall a b. (a -> b) -> a -> b
$ SWord8 -> SBool
a3 SWord8
birthMonth
SBool -> Predicate
forall (m :: * -> *) a. Monad m => a -> m a
return (SBool -> Predicate) -> SBool -> Predicate
forall a b. (a -> b) -> a -> b
$ SWord8 -> SWord8 -> SBool
valid SWord8
birthMonth SWord8
birthDay
cheryl :: IO ()
cheryl :: IO ()
cheryl = AllSatResult -> IO ()
forall a. Show a => a -> IO ()
print (AllSatResult -> IO ()) -> IO AllSatResult -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Predicate -> IO AllSatResult
forall a. Provable a => a -> IO AllSatResult
allSat Predicate
puzzle