aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--aoc-2022-dotnet/Common/Util.fs15
-rw-r--r--aoc-2022-dotnet/Day21/Program.fs52
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