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