import Data.String import System.File.ReadWrite data Result = Win | Loss | Draw -- Score value of a result for us scoreResult : Result -> Int scoreResult Win = 6 scoreResult Loss = 0 scoreResult Draw = 3 -- Parse a result from a string parseResult : String -> Maybe Result parseResult "X" = Just Loss parseResult "Y" = Just Draw parseResult "Z" = Just Win parseResult x = Nothing data Move = Rock | Paper | Scissors -- Determine the Result for a pair of moves -- First argument is their move, second argument is our move eval : Move -> Move -> Result eval Rock Rock = Draw eval Rock Paper = Win eval Rock Scissors = Loss eval Paper Rock = Loss eval Paper Paper = Draw eval Paper Scissors = Win eval Scissors Rock = Win eval Scissors Paper = Loss eval Scissors Scissors = Draw -- Score for an individual move scoreMove : Move -> Int scoreMove Rock = 1 scoreMove Paper = 2 scoreMove Scissors = 3 -- Parse a move from a string parseMove : String -> Maybe Move parseMove "A" = Just Rock parseMove "B" = Just Paper parseMove "C" = Just Scissors parseMove "X" = Just Rock parseMove "Y" = Just Paper parseMove "Z" = Just Scissors parseMove x = Nothing -- Get the move that gives the desired result getResult : Move -> Result -> Move getResult Rock Win = Paper getResult Rock Loss = Scissors getResult Rock Draw = Rock getResult Paper Win = Scissors getResult Paper Loss = Rock getResult Paper Draw = Paper getResult Scissors Win = Rock getResult Scissors Loss = Paper getResult Scissors Draw = Scissors data Round = R Move Move -- Score a round scoreRound : Round -> Int scoreRound (R a b) = scoreMove b + scoreResult (eval a b) -- Parse a round from a string parseRound : String -> Maybe Round parseRound input = let inputWords = words input in case inputWords of [a, b] => do theirs <- parseMove a ours <- parseMove b Just (R theirs ours) x => Nothing data Strategy = S Move Result -- Create the round that results from this strategy getRound : Strategy -> Round getRound (S a b) = R a (getResult a b) -- Parse a strategy from a string parseStrategy : String -> Maybe Strategy parseStrategy input = let inputWords = words input in case inputWords of [a, b] => do theirs <- parseMove a ours <- parseResult b Just (S theirs ours) x => Nothing main: IO () main = do file <- readFile "input" case file of Right content => let rounds = catMaybes . map parseRound . lines $ content strats = catMaybes . map parseStrategy . lines $ content in do putStr "Part 1: " printLn $ foldl (+) 0 (map scoreRound rounds) putStr "Part 2: " printLn $ foldl (+) 0 (map scoreRound . map getRound $ strats) Left err => printLn err