{-# OPTIONS_GHC -Wall -Werror #-}
module Documentation.SBV.Examples.Puzzles.Coins where
import Data.SBV
type Coin = SWord16
mkCoin :: Int -> Symbolic Coin
mkCoin :: Int -> Symbolic Coin
mkCoin Int
i = do Coin
c <- forall a. SymVal a => String -> Symbolic (SBV a)
sbvExists forall a b. (a -> b) -> a -> b
$ Char
'c' forall a. a -> [a] -> [a]
: forall a. Show a => a -> String
show Int
i
forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain forall a b. (a -> b) -> a -> b
$ forall a. (a -> SBool) -> [a] -> SBool
sAny (forall a. EqSymbolic a => a -> a -> SBool
.== Coin
c) [Coin
1, Coin
5, Coin
10, Coin
25, Coin
50, Coin
100]
forall (m :: * -> *) a. Monad m => a -> m a
return Coin
c
combinations :: [a] -> [[a]]
combinations :: forall a. [a] -> [[a]]
combinations [a]
coins = forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [forall {t} {a}. (Eq t, Num t) => t -> [a] -> [[a]]
combs Int
i [a]
coins | Int
i <- [Int
1 .. forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
coins]]
where combs :: t -> [a] -> [[a]]
combs t
0 [a]
_ = [[]]
combs t
_ [] = []
combs t
k (a
x:[a]
xs) = forall a b. (a -> b) -> [a] -> [b]
map (a
xforall a. a -> [a] -> [a]
:) (t -> [a] -> [[a]]
combs (t
kforall a. Num a => a -> a -> a
-t
1) [a]
xs) forall a. [a] -> [a] -> [a]
++ t -> [a] -> [[a]]
combs t
k [a]
xs
c1 :: [Coin] -> SBool
c1 :: [Coin] -> SBool
c1 [Coin]
xs = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Coin]
xs forall a. EqSymbolic a => a -> a -> SBool
./= Coin
100
c2 :: [Coin] -> SBool
c2 :: [Coin] -> SBool
c2 [Coin]
xs = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Coin]
xs forall a. EqSymbolic a => a -> a -> SBool
./= Coin
50
c3 :: [Coin] -> SBool
c3 :: [Coin] -> SBool
c3 [Coin]
xs = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Coin]
xs forall a. EqSymbolic a => a -> a -> SBool
./= Coin
25
c4 :: [Coin] -> SBool
c4 :: [Coin] -> SBool
c4 [Coin]
xs = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Coin]
xs forall a. EqSymbolic a => a -> a -> SBool
./= Coin
10
c5 :: [Coin] -> SBool
c5 :: [Coin] -> SBool
c5 [Coin]
xs = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Coin]
xs forall a. EqSymbolic a => a -> a -> SBool
./= Coin
5
c6 :: [Coin] -> SBool
c6 :: [Coin] -> SBool
c6 [Coin]
xs = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum (forall a b. (a -> b) -> [a] -> [b]
map forall {a}. (Mergeable a, EqSymbolic a, Num a) => a -> a
val [Coin]
xs) forall a. EqSymbolic a => a -> a -> SBool
./= Coin
95
where val :: a -> a
val a
x = forall a. Mergeable a => SBool -> a -> a -> a
ite (a
x forall a. EqSymbolic a => a -> a -> SBool
.== a
50) a
0 a
x
puzzle :: IO SatResult
puzzle :: IO SatResult
puzzle = forall a. Provable a => a -> IO SatResult
sat forall a b. (a -> b) -> a -> b
$ do
[Coin]
cs <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Int -> Symbolic Coin
mkCoin [Int
1..Int
6]
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain [[Coin] -> SBool
c [Coin]
s | [Coin]
s <- forall a. [a] -> [[a]]
combinations [Coin]
cs, forall (t :: * -> *) a. Foldable t => t a -> Int
length [Coin]
s forall a. Ord a => a -> a -> Bool
>= Int
2, [Coin] -> SBool
c <- [[Coin] -> SBool
c1, [Coin] -> SBool
c2, [Coin] -> SBool
c3, [Coin] -> SBool
c4, [Coin] -> SBool
c5, [Coin] -> SBool
c6]]
forall (m :: * -> *). SolverContext m => SBool -> m ()
constrain forall a b. (a -> b) -> a -> b
$ [SBool] -> SBool
sAnd forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall a. OrdSymbolic a => a -> a -> SBool
(.>=) [Coin]
cs (forall a. [a] -> [a]
tail [Coin]
cs)
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Coin]
cs forall a. EqSymbolic a => a -> a -> SBool
.== Coin
115