2022-12-03 13:29:11 -05:00
|
|
|
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
|
|
|
|
|
2022-12-03 13:52:10 -05:00
|
|
|
-- 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
|
|
|
|
|
2022-12-03 13:29:11 -05:00
|
|
|
main : IO ()
|
|
|
|
main =
|
|
|
|
do file <- readFile "input"
|
|
|
|
case file of
|
|
|
|
Right content =>
|
|
|
|
let backpacks = catMaybes . map parseBackpack . lines $ content
|
2022-12-03 13:52:10 -05:00
|
|
|
priorityTotals = sum . map (sum . map priority . duplicatedItems) $ backpacks
|
|
|
|
elves = chunk 3 backpacks
|
|
|
|
badges = map shared elves
|
|
|
|
badgeTotal = sum . map (sum . map priority) $ badges
|
2022-12-03 13:29:11 -05:00
|
|
|
in do putStr "part 1: "
|
|
|
|
printLn priorityTotals
|
2022-12-03 13:52:10 -05:00
|
|
|
putStr "part 2: "
|
|
|
|
printLn badgeTotal
|
2022-12-03 13:29:11 -05:00
|
|
|
Left err => printLn err
|