{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -Wall -Werror #-}
module Documentation.SBV.Examples.Puzzles.Birthday where
import Data.SBV
data Month = May | Jun | Jul | Aug
data Day = D14 | D15 | D16 | D17 | D18 | D19
mkSymbolicEnumeration ''Month
mkSymbolicEnumeration ''Day
data Birthday = BD SMonth SDay
mkBirthday :: Symbolic Birthday
mkBirthday :: Symbolic Birthday
mkBirthday = do b <- SMonth -> SDay -> Birthday
BD (SMonth -> SDay -> Birthday)
-> SymbolicT IO SMonth -> SymbolicT IO (SDay -> Birthday)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> SymbolicT IO SMonth
forall a. SymVal a => String -> Symbolic (SBV a)
free String
"birthMonth" SymbolicT IO (SDay -> Birthday)
-> SymbolicT IO SDay -> Symbolic Birthday
forall a b.
SymbolicT IO (a -> b) -> SymbolicT IO a -> SymbolicT IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> String -> SymbolicT IO SDay
forall a. SymVal a => String -> Symbolic (SBV a)
free String
"birthDay"
constrain $ valid b
pure b
valid :: Birthday -> SBool
valid :: Birthday -> SBool
valid (BD SMonth
m SDay
d) = (SMonth
m SMonth -> SMonth -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SMonth
sMay SBool -> SBool -> SBool
.=> SDay
d SDay -> [SDay] -> SBool
forall a. EqSymbolic a => a -> [a] -> SBool
`sElem` [SDay
sD15, SDay
sD16, SDay
sD19])
SBool -> SBool -> SBool
.&& (SMonth
m SMonth -> SMonth -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SMonth
sJun SBool -> SBool -> SBool
.=> SDay
d SDay -> [SDay] -> SBool
forall a. EqSymbolic a => a -> [a] -> SBool
`sElem` [SDay
sD17, SDay
sD18])
SBool -> SBool -> SBool
.&& (SMonth
m SMonth -> SMonth -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SMonth
sJul SBool -> SBool -> SBool
.=> SDay
d SDay -> [SDay] -> SBool
forall a. EqSymbolic a => a -> [a] -> SBool
`sElem` [SDay
sD14, SDay
sD16])
SBool -> SBool -> SBool
.&& (SMonth
m SMonth -> SMonth -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SMonth
sAug SBool -> SBool -> SBool
.=> SDay
d SDay -> [SDay] -> SBool
forall a. EqSymbolic a => a -> [a] -> SBool
`sElem` [SDay
sD14, SDay
sD15, SDay
sD17])
puzzle :: ConstraintSet
puzzle :: ConstraintSet
puzzle = do BD birthMonth birthDay <- Symbolic Birthday
mkBirthday
let ok = (Birthday -> SBool) -> [Birthday] -> SBool
forall a. (a -> SBool) -> [a] -> SBool
sAll Birthday -> SBool
valid
qe a
qb = a -> SBool
forall a. QuantifiedBool a => a -> SBool
quantifiedBool a
qb
let a1 SMonth
m = (Exists (ZonkAny 2) Day -> Exists (ZonkAny 3) Day -> SBool)
-> SBool
forall a. QuantifiedBool a => a -> SBool
qe ((Exists (ZonkAny 2) Day -> Exists (ZonkAny 3) Day -> SBool)
-> SBool)
-> (Exists (ZonkAny 2) Day -> Exists (ZonkAny 3) Day -> SBool)
-> SBool
forall a b. (a -> b) -> a -> b
$ \(Exists SDay
d1) (Exists SDay
d2) -> [Birthday] -> SBool
ok [SMonth -> SDay -> Birthday
BD SMonth
m SDay
d1, SMonth -> SDay -> Birthday
BD SMonth
m SDay
d2] SBool -> SBool -> SBool
.&& SDay
d1 SDay -> SDay -> SBool
forall a. EqSymbolic a => a -> a -> SBool
./= SDay
d2
constrain $ a1 birthMonth
let a2 SMonth
m = (Forall (ZonkAny 4) Day -> SBool) -> SBool
forall a. QuantifiedBool a => a -> SBool
qe ((Forall (ZonkAny 4) Day -> SBool) -> SBool)
-> (Forall (ZonkAny 4) Day -> SBool) -> SBool
forall a b. (a -> b) -> a -> b
$ \(Forall SDay
d) -> [Birthday] -> SBool
ok [SMonth -> SDay -> Birthday
BD SMonth
m SDay
d] SBool -> SBool -> SBool
.=> (Exists (ZonkAny 5) Month -> Exists (ZonkAny 6) Month -> SBool)
-> SBool
forall a. QuantifiedBool a => a -> SBool
qe (\(Exists SMonth
m1) (Exists SMonth
m2) -> [Birthday] -> SBool
ok [SMonth -> SDay -> Birthday
BD SMonth
m1 SDay
d, SMonth -> SDay -> Birthday
BD SMonth
m2 SDay
d] SBool -> SBool -> SBool
.&& SMonth
m1 SMonth -> SMonth -> SBool
forall a. EqSymbolic a => a -> a -> SBool
./= SMonth
m2)
constrain $ a2 birthMonth
let b1 SDay
d = (Exists (ZonkAny 7) Month -> Exists (ZonkAny 8) Month -> SBool)
-> SBool
forall a. QuantifiedBool a => a -> SBool
qe ((Exists (ZonkAny 7) Month -> Exists (ZonkAny 8) Month -> SBool)
-> SBool)
-> (Exists (ZonkAny 7) Month -> Exists (ZonkAny 8) Month -> SBool)
-> SBool
forall a b. (a -> b) -> a -> b
$ \(Exists SMonth
m1) (Exists SMonth
m2) -> [Birthday] -> SBool
ok [SMonth -> SDay -> Birthday
BD SMonth
m1 SDay
d, SMonth -> SDay -> Birthday
BD SMonth
m2 SDay
d] SBool -> SBool -> SBool
.&& SMonth
m1 SMonth -> SMonth -> SBool
forall a. EqSymbolic a => a -> a -> SBool
./= SMonth
m2
constrain $ b1 birthDay
let b2p SMonth
m SDay
d = [Birthday] -> SBool
ok [SMonth -> SDay -> Birthday
BD SMonth
m SDay
d] SBool -> SBool -> SBool
.&& SMonth -> SBool
a1 SMonth
m SBool -> SBool -> SBool
.&& SMonth -> SBool
a2 SMonth
m
b2 SDay
d = (Forall (ZonkAny 9) Month -> Forall (ZonkAny 10) Month -> SBool)
-> SBool
forall a. QuantifiedBool a => a -> SBool
qe ((Forall (ZonkAny 9) Month -> Forall (ZonkAny 10) Month -> SBool)
-> SBool)
-> (Forall (ZonkAny 9) Month -> Forall (ZonkAny 10) Month -> SBool)
-> SBool
forall a b. (a -> b) -> a -> b
$ \(Forall SMonth
m1) (Forall SMonth
m2) -> (SMonth -> SDay -> SBool
b2p SMonth
m1 SDay
d SBool -> SBool -> SBool
.&& SMonth -> SDay -> SBool
b2p SMonth
m2 SDay
d) SBool -> SBool -> SBool
.=> SMonth
m1 SMonth -> SMonth -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SMonth
m2
constrain $ b2 birthDay
let a3p SMonth
m SDay
d = [Birthday] -> SBool
ok [SMonth -> SDay -> Birthday
BD SMonth
m SDay
d] SBool -> SBool -> SBool
.&& SMonth -> SBool
a1 SMonth
m SBool -> SBool -> SBool
.&& SMonth -> SBool
a2 SMonth
m SBool -> SBool -> SBool
.&& SDay -> SBool
b1 SDay
d SBool -> SBool -> SBool
.&& SDay -> SBool
b2 SDay
d
a3 SMonth
m = \(Forall SDay
d1) (Forall SDay
d2) -> (SMonth -> SDay -> SBool
a3p SMonth
m SDay
d1 SBool -> SBool -> SBool
.&& SMonth -> SDay -> SBool
a3p SMonth
m SDay
d2) SBool -> SBool -> SBool
.=> SDay
d1 SDay -> SDay -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SDay
d2
constrain $ a3 birthMonth
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
=<< ConstraintSet -> IO AllSatResult
forall a. Satisfiable a => a -> IO AllSatResult
allSat ConstraintSet
puzzle