import Data.List
import Debug.Trace

addFirst :: [[a]] -> a -> [[a]]
addFirst [] x = [[x]]
addFirst (y:ys) x = ([x] ++ y) : ys

split :: [Char] -> [Char] -> [[Char]]
split _ [] = []
split delims (x:xs)
  | elem x delims = [[]] ++ split delims xs
  | otherwise     = addFirst (split delims xs) x


splitInput :: String -> [(Int, [Int])]
splitInput text = map (\(x:xs) -> (x, xs)) $ map (map read) $ map (filter (/="")) $ map (split [' ', ':']) $ split ['\n'] text

solve1 :: [(Int, [Int])] -> Int
solve1 [] = 0
solve1 ((_, []):xs) = solve1 xs
solve1 ((a, (b:bs)):xs) = ((\x -> if x then 0 else a) $ null $ filter (==a) $ map (\fs -> (foldl' (flip ($)) b (zipWith flip fs bs))) (getOperators (length bs))) + solve1 xs

getOperators :: (Num a, Show a) => Int -> [[(a -> a -> a)]]
getOperators 0 = [[]]
getOperators x
  | x < 0     = [[]]
  | otherwise = (map (\x -> (+):x) (getOperators (x-1))) ++ (map (\x -> (*):x) (getOperators (x-1)))

solve2 :: [(Int, [Int])] -> Int
solve2 [] = 0
solve2 ((_, []):xs) = solve2 xs
solve2 ((a, (b:bs)):xs) = ((\x -> if x then 0 else a) $ null $ filter (==a) $ map (\fs -> (foldl' (flip ($)) b (zipWith flip fs bs))) (getOperators2 (length bs))) + solve2 xs

getOperators2 :: (Num a, Show a, Read a) => Int -> [[(a -> a -> a)]]
getOperators2 0 = [[]]
getOperators2 x
  | x < 0     = [[]]
  | otherwise = (map (\x -> (+):x) (getOperators2 (x-1))) ++ (map (\x -> (*):x) (getOperators2 (x-1))) ++ (map (\x -> concat':x) (getOperators2 (x-1)))

concat' :: (Show a, Read a) => a -> a -> a
concat' x y = read ((show x) ++ (show y))

main :: IO()
main = do
       fileinp <- readFile "input.txt"
       let parsed = splitInput fileinp
       let solved1 = solve1 parsed
       let solved2 = solve2 parsed
       print solved1
       print solved2
