-
Notifications
You must be signed in to change notification settings - Fork 0
/
day2.hs
84 lines (68 loc) · 2.14 KB
/
day2.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
data Move = Rock | Paper | Scissors deriving (Eq, Read, Show)
data Outcome = Win | Draw | Lose deriving (Show)
-- opponent move, our move
type Round = (Move, Move)
type IdealRound = (Move, Outcome)
parseMove :: Char -> Move
parseMove 'A' = Rock
parseMove 'B' = Paper
parseMove 'C' = Scissors
parseMove 'X' = Rock
parseMove 'Y' = Paper
parseMove 'Z' = Scissors
parseMove _ = error "invalid move"
parseOutcome :: Char -> Outcome
parseOutcome 'X' = Lose
parseOutcome 'Y' = Draw
parseOutcome 'Z' = Win
parse :: String -> Round
parse (o:' ':p:[]) = (parseMove o, parseMove p)
parse _ = error "invalid round"
parse' :: String -> IdealRound
parse' (o:' ':p:[]) = (parseMove o, parseOutcome p)
parse' _ = error "invalid round"
shapeScore :: Move -> Int
shapeScore Rock = 1
shapeScore Paper = 2
shapeScore Scissors = 3
play :: Move -> Move -> Outcome
play Rock Paper = Win
play Paper Scissors = Win
play Scissors Rock = Win
play a b | a == b = Draw
play _ _ = Lose
outcomeScore :: Outcome -> Int
outcomeScore Win = 6
outcomeScore Draw = 3
outcomeScore _ = 0
makeWin :: Move -> Move
makeWin Rock = Paper
makeWin Paper = Scissors
makeWin Scissors = Rock
makeDraw :: Move -> Move
makeDraw m = m
makeLoss :: Move -> Move
makeLoss Rock = Scissors
makeLoss Paper = Rock
makeLoss Scissors = Paper
makeOutcome :: Outcome -> Move -> Move
makeOutcome Win = makeWin
makeOutcome Draw = makeDraw
makeOutcome Lose = makeLoss
score :: Round -> Int
score (o, p) = shapeScore p + (outcomeScore $ play o p)
score' :: IdealRound -> Int
score' (m, o) = score (m, p)
where p = makeOutcome o m
finalScore :: String -> IO Int
finalScore file = do contents <- readFile file
let rounds = map (parse) $ filter (\l -> l /= "") $ lines contents
let scores = map (score) rounds
let total = sum scores
return total
finalScore' :: String -> IO Int
finalScore' file = do contents <- readFile file
let rounds = map (parse') $ filter (\l -> l /= "") $ lines contents
let scores = map (score') rounds
let total = sum scores
return total