aboutsummaryrefslogtreecommitdiff
path: root/aoc-2022-dotnet/Day21/Program.fs
blob: 383705493442de87444b08adac915bd4ff26b5cd (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
module Day21

open System.IO
open FSharpPlus
open FParsec
open Common

type MonkeyName = string
type Operator = int64 -> int64 -> int64

type MonkeyJob =
    | Number of int64
    | Operation of MonkeyName * Operator * MonkeyName

    static member dependencies =
        function
        | Number _ -> []
        | Operation (l, _, r) -> [ l; r ]

type Monkey = MonkeyName * MonkeyJob

let charToOperator =
    function
    | '+' -> (+)
    | '-' -> (-)
    | '*' -> (*)
    | '/' -> (/)
    | c -> failwithf "Invalid operator: %c" c

let parseMonkey =
    let pspc = pchar ' '
    let pname = anyString 4 |>> MonkeyName
    let poper = pspc >>. anyChar .>> pspc |>> charToOperator
    let pnumber = pint64 |>> Number
    let poperation = tuple3 pname poper pname |>> Operation
    let pjob = pnumber <|> poperation
    let pmonkey = pname .>> pstring ": " .>>. pjob |>> Monkey
    Util.parse pmonkey

let solution input =
    let monkeys = input |> Seq.map parseMonkey |> Map.ofSeq

    monkeys
    |> Map.mapValues MonkeyJob.dependencies
    |> Util.tsort
    |> List.fold
        (fun values name ->
            Map.add
                name
                (match monkeys[name] with
                 | Number num -> num
                 | Operation (left, operator, right) -> operator values[left] values[right])
                values)
        Map.empty
    |> Map.find "root"

let test = File.ReadLines("test.txt")
assert (solution test = 152)

let input = File.ReadLines("input.txt")
printfn "%d" <| solution input