module Day3.Main (main) where import System.IO import Data.Char import Data.List.Split main :: IO () main = do putStrLn "Day 3" handle <- openFile "app/Day3/input" ReadMode contents <- hGetContents handle let r1 = part1 contents putStrLn $ "part 1: " ++ show r1 let r2 = part2 contents putStrLn $ "part 2: " ++ show r2 type Rucksack = (String, String) parseData :: String -> [Rucksack] parseData input = zip firstCompartments secondCompartments where rucksacks = lines input compartmentSize = map ((`div` 2) . length) rucksacks firstCompartments = map (uncurry take) (zip compartmentSize rucksacks) secondCompartments = map (uncurry drop) (zip compartmentSize rucksacks) inBoth :: Eq a => [a] -> [a] -> [a] inBoth a b = [x | x <- a, y <- b, x == y] allEqual :: Eq a => [a] -> Bool allEqual [] = True allEqual (x:xs) = all (== x) xs inAll :: Eq a => [[a]] -> [a] inAll xs = map ((!! 0) . snd) res where prod = sequence xs equal = map allEqual prod res = filter fst (zip equal prod) getValue :: Char -> Int getValue a | a >= 'a' && a <= 'z' = ord a - ord 'a' + 1 getValue a | a >= 'A' && a <= 'Z' = ord a - ord 'A' + 1 + 26 part1 :: String -> Int part1 contents = sum values where both = map (uncurry inBoth) (parseData contents) single = map (!! 0) both values = map getValue single part2 :: String -> Int part2 contents = sum values where groups = chunksOf 3 (lines contents) badges = map ((!! 0) . inAll) groups values = map getValue badges