diff options
-rw-r--r-- | aoc-2022-dotnet/Common/Util.fs | 15 | ||||
-rw-r--r-- | aoc-2022-dotnet/Day21/Program.fs | 52 |
2 files changed, 67 insertions, 0 deletions
diff --git a/aoc-2022-dotnet/Common/Util.fs b/aoc-2022-dotnet/Common/Util.fs index 568f2c2..ac5d981 100644 --- a/aoc-2022-dotnet/Common/Util.fs +++ b/aoc-2022-dotnet/Common/Util.fs @@ -65,6 +65,21 @@ module Util = | h :: t -> h, t @ [ h ] | [] -> failwith "Empty list!" + let tsort graph = + let dfs = + let rec explore path result node = + if List.contains node path then + failwith "Cycle found!" + elif List.contains node result then + result + else + node + :: List.fold (explore (node :: path)) result (Map.find node graph) + + explore [] + + graph |> Map.keys |> Seq.fold dfs [] |> List.rev + let topN n xs = Seq.fold (fun acc x -> diff --git a/aoc-2022-dotnet/Day21/Program.fs b/aoc-2022-dotnet/Day21/Program.fs index e5d8920..3837054 100644 --- a/aoc-2022-dotnet/Day21/Program.fs +++ b/aoc-2022-dotnet/Day21/Program.fs @@ -1,9 +1,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 |