62 lines
1.6 KiB
Haskell
62 lines
1.6 KiB
Haskell
|
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
|