Created
August 5, 2011 17:08
-
-
Save cqfd/1127997 to your computer and use it in GitHub Desktop.
Haskell solution to the 1,3,4,6 problem
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Control.Monad (mapM_) | |
main :: IO () | |
main = printSolutions 24 [1,3,4,6] "+-*/" | |
data BareTree a = BLeaf a | BBranch (BareTree a) (BareTree a) deriving Show | |
type Op = Char | |
toOp :: (Fractional a) => Op -> (a -> a -> a) | |
toOp '+' = (+) | |
toOp '-' = (-) | |
toOp '*' = (*) | |
toOp '/' = (/) | |
data ArithTree a = ALeaf a | ABranch Op (ArithTree a) (ArithTree a) | |
instance (Show a) => Show (ArithTree a) where | |
show (ALeaf x) = show x | |
show (ABranch op leftTree rightTree) = | |
"(" ++ show leftTree ++ ")" ++ [op] ++ "(" ++ show rightTree ++ ")" | |
insert :: a -> BareTree a -> [BareTree a] | |
insert x (BLeaf y) = | |
[BBranch (BLeaf x) (BLeaf y), BBranch (BLeaf y) (BLeaf x)] | |
insert x bt@(BBranch leftTree rightTree) = | |
let | |
leftPreInsert = BBranch (BLeaf x) bt | |
rightPreInsert = BBranch bt (BLeaf x) | |
leftSubInserts = do | |
leftSubInsert <- insert x leftTree | |
return (BBranch leftSubInsert rightTree) | |
rightSubInserts = do | |
rightSubInsert <- insert x rightTree | |
return (BBranch leftTree rightSubInsert) | |
in | |
[leftPreInsert, rightPreInsert] ++ leftSubInserts ++ rightSubInserts | |
allBareTrees :: [a] -> [BareTree a] | |
allBareTrees [x] = [BLeaf x] | |
allBareTrees (x:xs) = allBareTrees xs >>= insert x | |
opifyWith :: [Op] -> BareTree a -> [ArithTree a] | |
opifyWith _ (BLeaf x) = [ALeaf x] | |
opifyWith ops (BBranch leftTree rightTree) = do | |
op <- ops | |
opifiedLeftTree <- opifyWith ops leftTree | |
opifiedRightTree <- opifyWith ops rightTree | |
return (ABranch op opifiedLeftTree opifiedRightTree) | |
allArithTrees :: (Fractional a) => [a] -> [Op] -> [ArithTree a] | |
allArithTrees ints ops = allBareTrees ints >>= opifyWith ops | |
eval :: (Fractional a) => ArithTree a -> Maybe a | |
eval (ALeaf x) = return x | |
eval (ABranch '/' leftTree rightTree) = do | |
rightResult <- eval rightTree | |
if rightResult == 0 then | |
Nothing | |
else do | |
leftResult <- eval leftTree | |
return (toOp '/' leftResult rightResult) | |
eval (ABranch op leftTree rightTree) = do | |
leftResult <- eval leftTree | |
rightResult <- eval rightTree | |
return (toOp op leftResult rightResult) | |
findSolutions :: (Fractional a) => a -> [a] -> [Op] -> [ArithTree a] | |
findSolutions answer ints ops = | |
filter (\tree -> eval tree == Just answer) (allArithTrees ints ops) | |
printSolutions :: Fractional a => a -> [a] -> [Op] -> IO () | |
printSolutions answer ints ops = | |
let solutions = findSolutions answer ints ops | |
in mapM_ (putStrLn . show) solutions |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Cleaner using the StateT monad transformer on Maybe: