{-# LANGUAGE OverloadedStrings #-} import Data.List (foldl', foldl1') import Data.List.Split (chunksOf) import qualified Data.Set as S import Formatting main :: IO () main = do input <- readFile "input/day03.txt" let rucksacks = lines input duplicateSum = prioritySum . map splitHalfway $ rucksacks -- Expected: 8298 badgeSum = prioritySum . chunksOf 3 $ rucksacks -- Expected: 2708 fprintLn ("Part 1 (sum of duplicate element priorities): " % int) duplicateSum fprintLn ("Part 2 (sum of badge priorities): " % int) badgeSum where priorityAccumulator = flip ((+) . itemPriority . commonItem) prioritySum = foldl' priorityAccumulator 0 -- Numbers were chosen to make A map to 27 and a map to 1; everything else follows in ASCII :) itemPriority :: Char -> Int itemPriority item = mod (fromEnum item - 38) 58 -- Essentially splitAt but more convenient for reuse due to not returning a tuple splitHalfway :: String -> [String] splitHalfway line = [take halfLen line, drop halfLen line] where halfLen = div (length line) 2 -- This works because there should only be 1 common element in all cases commonItem :: [String] -> Char commonItem = S.elemAt 0 . foldl1' S.intersection . map S.fromList