adventofcode/2022/app/Day3/Main.hs

62 lines
1.6 KiB
Haskell
Raw Normal View History

2022-12-03 10:02:56 +01:00
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 = compartments
where
rucksacks = lines input
compartmentSize = map ((`div` 2) . length) rucksacks
firstCompartments = map (\(s, r) -> take s r) (zip compartmentSize rucksacks)
secondCompartments = map (\(s, r) -> drop s r) (zip compartmentSize rucksacks)
compartments = zip firstCompartments secondCompartments
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