aboutsummaryrefslogtreecommitdiff
path: root/aoc-2022-dotnet/Day02/Program.fs
blob: 8568f9a2839305d20a474422adf1e41e00b3e273 (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
module Day02

open System.IO
open FSharpPlus
open Common

type Move =
    | Rock
    | Paper
    | Scissors

    static member parse =
        function
        | "A" -> Rock
        | "B" -> Paper
        | "C" -> Scissors
        | s -> failwithf "Invalid move: %s" s

    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
        | s -> failwithf "Invalid strategy: %s" s

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) =
        roundStr
        |> Util.splitStringToTuple " "
        |> mapItem1 Move.parse
        |> mapItem2 Strategy.parse

    enemy, guide enemy strategy

let solution guide =
    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