You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

70 lines
1.6 KiB
Haskell

{-# LANGUAGE OverloadedStrings #-}
module Days.Day02 (day02) where
import AOC (Solution (..))
import Data.Bifunctor qualified as B
import Data.Text qualified as T
day02 :: Solution
day02 = Solution parseInput part1 part2
data Shape = Rock | Paper | Scissors
deriving (Eq)
data Outcome = Win | Lose | Draw
deriving (Eq)
toShape :: T.Text -> Shape
toShape c
| c == "A" || c == "X" = Rock
| c == "B" || c == "Y" = Paper
| c == "C" || c == "Z" = Scissors
| otherwise = error $ show c
toOutcome :: T.Text -> Outcome
toOutcome "X" = Lose
toOutcome "Y" = Draw
toOutcome "Z" = Win
toOutcome c = error $ show c
pScore :: Shape -> Int
pScore Rock = 1
pScore Paper = 2
pScore Scissors = 3
oScore :: (Shape, Shape) -> Int
oScore (opp, player)
| player == beats opp = 6
| player == loses opp = 0
| otherwise = 3
beats :: Shape -> Shape
beats Rock = Paper
beats Paper = Scissors
beats Scissors = Rock
loses :: Shape -> Shape
loses Rock = Scissors
loses Paper = Rock
loses Scissors = Paper
scores :: [(Shape, Shape)] -> [Int]
scores = map (\(o, p) -> oScore (o, p) + pScore p)
parseInput :: T.Text -> [(Shape, T.Text)]
parseInput = map convert . T.lines
where
convert line = let [fst, snd] = T.words line in (toShape fst, snd)
part1 :: [(Shape, T.Text)] -> Int
part1 input = sum $ scores $ map (B.second toShape) input
part2 :: [(Shape, T.Text)] -> Int
part2 input = sum $ scores $ map tupleToShape outcomes
where
outcomes = map (B.second toOutcome) input
tupleToShape (shape, Win) = (shape, beats shape)
tupleToShape (shape, Lose) = (shape, loses shape)
tupleToShape (shape, _) = (shape, shape)