import Debug.Trace import Data.Maybe import Data.List (***) :: (a -> a') -> (b -> b') -> (a, b) -> (a', b') (f *** g) (x, y) = (f x, g y) traceOut :: Show a => a -> a traceOut x = traceShow x x addFirst :: [[a]] -> a -> [[a]] addFirst [] x = [[x]] addFirst (y:ys) x = (x : y) : ys split :: Eq a => [a] -> [a] -> [[a]] split _ [] = [] split delims (x:xs) | x `elem` delims = [] : split delims xs | otherwise = addFirst (split delims xs) x data Symbol = Mul | Add instance Show Symbol where show Mul = "*" show Add = "+" toIdFunction :: Symbol -> (Int, (Int -> Int -> Int)) toIdFunction Mul = (1, (*)) toIdFunction Add = (0, (+)) toSymbol :: Char -> Maybe Symbol toSymbol '*' = Just Mul toSymbol '+' = Just Add toSymbol _ = Nothing parseFile1 :: String -> ([Symbol], [[Int]]) parseFile1 = (map (fromJust . toSymbol . head) *** (map (map read) . transpose)) . fromJust . uncons . reverse . map words . lines solve :: ([Symbol], [[Int]]) -> Int solve = sum . map (uncurry $ uncurry $ flip foldl) . (uncurry zip) . (map toIdFunction *** id) parseFile2 :: String -> ([Symbol], [[Int]]) parseFile2 = ((map (fromJust . toSymbol . head) . words) *** (map (map (read . reverse)) . split [""] . map (takeWhile (/= ' ') . dropWhile (== ' ')) . transpose)) . fromJust . uncons . reverse . lines main = do fileinp <- readFile "input.txt" let input1 = parseFile1 fileinp let solved1 = solve input1 print solved1 let input2 = parseFile2 fileinp let solved2 = solve input2 print solved2