import Control.Monad (mapM, foldM, forever) import Data.List (unwords, unlines, nub) import Data.Maybe (fromJust) truthTable expr = let tokens = words expr operators = ["&", "|", "!", "^", "=>"] variables = nub $ filter (not . (`elem` operators)) tokens table = zip variables <$> mapM (const [True,False]) variables results = map (\r -> (map snd r) ++ (calculate tokens) r) table header = variables ++ ["result"] in showTable $ header : map (map show) results -- Performs evaluation of token sequence in a given context. -- The context is an assoc-list, which binds variable and it's value. -- Here the monad is simple ((->) r). calculate :: [String] -> [(String, Bool)] -> [Bool] calculate = foldM interprete [] where interprete (x:y:s) "&" = (: s) <$> pure (x && y) interprete (x:y:s) "|" = (: s) <$> pure (x || y) interprete (x:y:s) "^" = (: s) <$> pure (x /= y) interprete (x:y:s) "=>" = (: s) <$> pure (not y || x) interprete (x:s) "!" = (: s) <$> pure (not x) interprete s var = (: s) <$> fromJust . lookup var -- pretty printing showTable tbl = unlines $ map (unwords . map align) tbl where align txt = take colWidth $ txt ++ repeat ' ' colWidth = max 6 $ maximum $ map length (head tbl) main = forever $ getLine >>= putStrLn . truthTable