import System.File.ReadWrite import Data.String import Data.List data Item = I Char Eq Item where (I a) == (I b) = a == b Show Item where show (I a) = show a -- Define the priority of item priority : Item -> Int priority (I char) = if isUpper char then ord char - 38 else ord char - 96 -- Spiit a list in half splitHalf : List a -> Maybe (List a, List a) splitHalf list = let len : Int len = cast $ length list halfLen : Int halfLen = div len 2 resultLen : Nat resultLen = cast halfLen in if len `mod` 2 == 0 then Just (take resultLen list, drop resultLen list) else Nothing data Backpack = B (List Item) (List Item) -- Parse a backpack from a string parseBackpack : String -> Maybe Backpack parseBackpack input = let items = map I . unpack $ input in do (left, right) <- splitHalf items Just (B left right) -- Get the duplicated items duplicatedItems : Backpack -> List Item duplicatedItems (B left right) = nub $ intersect left right -- Shared items across a collection of backpack shared : List Backpack -> List Item shared xs = let combined = map (\(B left right) => left ++ right ) xs in nub . intersectAll $ combined -- Chunk a list chunk : Nat -> List a -> List (List a) chunk x [] = [] chunk x xs = let head = take x xs tail = chunk x . drop x $ xs in head :: tail main : IO () main = do file <- readFile "input" case file of Right content => let backpacks = catMaybes . map parseBackpack . lines $ content priorityTotals = sum . map (sum . map priority . duplicatedItems) $ backpacks elves = chunk 3 backpacks badges = map shared elves badgeTotal = sum . map (sum . map priority) $ badges in do putStr "part 1: " printLn priorityTotals putStr "part 2: " printLn badgeTotal Left err => printLn err