8000 docs(day2): comment day2 explicitly for non-haskell folks · IndecisionTree/adventofcode2022@646874c · GitHub
[go: up one dir, main page]

Skip to content

Commit 646874c

Browse files
docs(day2): comment day2 explicitly for non-haskell folks
1 parent 7fe09ce commit 646874c

File tree

1 file changed

+30
-12
lines changed

1 file changed

+30
-12
lines changed

solutions/Days/Day02.hs

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,73 @@
11
module Days.Day02 (day02) where
22

33
import AOC (Solution (..))
4-
import Control.Arrow ((>>>), (***), second)
4+
import Control.Arrow ((<<<), (***), second)
55
import Data.Maybe (fromMaybe)
66
import qualified Data.Text as T
77

88
day02 :: Solution
99
day02 = Solution parseInput part1 part2
1010

11+
-- | an RPS move
1112
data RPS = Rock | Paper | Scissors
1213
deriving (Show, Eq, Enum, Bounded)
1314

14-
data Action = Lose | Draw | Win
15+
-- | a game outcome
16+
data Outcome = Lose | Draw | Win
1517
deriving (Show, Eq)
1618

19+
-- | Parse the input into tuples consisting of (RPS move, "XYZ" Char).
1720
parseInput :: T.Text -> [(RPS, T.Text)]
18-
parseInput = fmap (T.breakOn " " >>> translate table *** T.tail) . T.lines
21+
parseInput = fmap (lookup' table *** T.tail <<< T.breakOn " ") . T.lines
1922
where
2023
table = [("A", Rock), ("B", Paper), ("C", Scissors)]
2124

25+
-- | Part 1, translate the "XYZ" chars into RPS moves, score the
26+
-- results, sum them together.
2227
part1 :: [(RPS, T.Text)] -> Int
23-
part1 = sum . fmap (score . second (translate table))
28+
part1 = sum . fmap (score . second (lookup' table))
2429
where
2530
table = [("X", Rock), ("Y", Paper), ("Z", Scissors)]
2631

32+
-- | Part 2, translate the "XYZ" chars into game outcome Actions,
33+
-- match those actions with the necessary RPS move to achieve the
34+
-- desired action, score the results, and sum them together.
2735
part2 :: [(RPS, T.Text)] -> Int
28-
part2 = sum . fmap (score . matchAction . second (translate table))
36+
part2 = sum . fmap (score . matchAction . second (lookup' table))
2937
where
3038
table = [("X", Lose), ("Y", Draw), ("Z", Win)]
3139

32-
translate :: (Show a, Eq a) => [(a, b)] -> a -> b
33-
translate table ch =
34-
fromMaybe (error $ "Lookup failed: " ++ show ch) $ lookup ch table
40+
-- | Wrapper around 'lookup' that 'error's out if the lookup fails.
41+
lookup' :: (Show a, Eq a) => [(a, b)] -> a -> b
42+
lookup' table a =
43+
fromMaybe (error $ "Lookup failed: " ++ show a) $ lookup a table
3544

36-
matchAction :: (RPS, Action) -> (RPS, RPS)
45+
-- | Translate a desired 'Outcome' into an 'RPS' move based on the
46+
-- 'RPS' move given for player 1 in the first tuple position.
47+
matchAction :: (RPS, Outcome) -> (RPS, RPS)
3748
matchAction (rps, action) = (rps, match)
3849
where
3950
match = case action of
4051
Lose -> prevRPS rps
4152
Draw -> rps
4253
Win -> nextRPS rps
4354

55+
-- | Score an RPS round. Uses the derived 'Enum' instance for 'RPS' to
56+
-- determine a moves individual value.
4457
score :: (RPS, RPS) -> Int
4558
score (a, b) = (fromEnum b + 1) + beats a b
4659

60+
-- | Determine the points received by player 2 when facing player 1's
61+
-- move.
4762
beats :: RPS -> RPS -> Int
48-
beats a b
49-
| nextRPS a == b = 6
50-
| a == b = 3
63+
beats p1 p2
64+
| nextRPS p1 == p2 = 6
65+
| p1 == p2 = 3
5166
| otherwise = 0
5267

68+
-- | Bounded successor/predecessor for 'RPS' with wrap-around at both
69+
-- upper and lower bounds. Uses 'RPS's derived 'Enum' and 'Bounded'
70+
-- instances.
5371
nextRPS, prevRPS :: RPS -> RPS
5472
nextRPS rps
5573
| rps == maxBound = minBound

0 commit comments

Comments
 (0)
0