1 -- Writeup at https://work.njae.me.uk/2022/12/03/advent-of-code-2022-day-3/
5 import qualified Data.Set as S
9 type Contents = S.Set Char
10 data Rucksack = Rucksack String String deriving (Show, Eq)
14 do dataFileName <- getDataFileName
15 text <- readFile dataFileName
16 let rucksacks = fmap mkRucksack $ lines text
17 print $ part1 rucksacks
18 print $ part2 rucksacks
20 part1 :: [Rucksack] -> Int
21 part1 = sum . fmap (priority . commonItem)
23 part2 :: [Rucksack] -> Int
24 part2 rucksacks = sum $ fmap priority badges
25 where groups = chunksOf 3 rucksacks
26 badges = fmap badgeOf groups
28 merge :: Rucksack -> Contents
29 merge (Rucksack contents1 contents2) =
30 S.union (S.fromList contents1) (S.fromList contents2)
32 badgeOf :: [Rucksack] -> Char
33 badgeOf rucksacks = S.findMin $ intersections (fmap merge rucksacks)
35 intersections :: [Contents] -> Contents
36 intersections sets = foldl1' S.intersection sets
39 mkRucksack :: String -> Rucksack
40 mkRucksack contents = Rucksack (take n contents) (drop n contents)
41 where n = length contents `div` 2
43 commonItem :: Rucksack -> Char
44 commonItem (Rucksack contents1 contents2) = S.findMin (c1 `S.intersection` c2)
45 where c1 = S.fromList contents1
46 c2 = S.fromList contents2
48 priority :: Char -> Int
50 | isLower item = ord item - ord 'a' + 1
51 | otherwise = ord item - ord 'A' + 27