blob: b14339022b9659baf42583b658fceb6b90ab4bee (
plain)
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
85
86
87
|
open System.IO
open FSharpPlus
type Move =
| Rock
| Paper
| Scissors
static member parse =
function
| "A" -> Rock
| "B" -> Paper
| "C" -> Scissors
| _ -> failwith "Invalid move string!"
static member choices = [ Rock; Paper; Scissors ]
member first.beats second =
match (first, second) with
| (Rock, Scissors)
| (Scissors, Paper)
| (Paper, Rock) -> true
| _ -> false
type Strategy =
| X
| Y
| Z
static member parse =
function
| "X" -> X
| "Y" -> Y
| "Z" -> Z
| _ -> failwith "Invalid strategy string!"
let splitToTuple sep str =
match String.split [ sep ] str |> Seq.toList with
| [ x; y ] -> x, y
| _ -> failwith "Invalid string format!"
let scoreRound (enemy, player) =
let selectionScore =
match player with
| Rock -> 1
| Paper -> 2
| Scissors -> 3
let outcomeScore =
if player.beats enemy then 6
elif player = enemy then 3
else 0
selectionScore + outcomeScore
let guide1 _ =
function
| X -> Rock
| Y -> Paper
| Z -> Scissors
let guide2 (enemy: Move) =
function
| X -> Seq.find (fun player -> enemy.beats player) Move.choices
| Y -> enemy
| Z -> Seq.find (fun player -> player.beats enemy) Move.choices
let parseRound guide roundStr =
let (enemy, strategy) =
splitToTuple " " roundStr
|> mapItem1 Move.parse
|> mapItem2 Strategy.parse
enemy, guide enemy strategy
let solution guide input =
input
|> Seq.map (parseRound guide)
|> Seq.sumBy scoreRound
let test = File.ReadLines "test.txt"
assert (solution guide1 test = 15)
assert (solution guide2 test = 12)
let input = File.ReadLines "input.txt"
printfn "%d" (solution guide1 input)
printfn "%d" (solution guide2 input)
|