diff options
author | Tomasz Chojnacki <tomaszchojnacki2001@gmail.com> | 2022-12-28 20:33:21 +0100 |
---|---|---|
committer | Tomasz Chojnacki <tomaszchojnacki2001@gmail.com> | 2022-12-28 20:33:21 +0100 |
commit | ac81191905118139c5461ee552c1ee06e4f8544b (patch) | |
tree | cccb81ff845dfa9d0655545aa02dd04bf39072df /aoc-2022-dotnet | |
parent | 8e71f049f5ffce904fcd477dbb019e794391c595 (diff) | |
download | gleam_aoc2020-ac81191905118139c5461ee552c1ee06e4f8544b.tar.gz gleam_aoc2020-ac81191905118139c5461ee552c1ee06e4f8544b.zip |
Finish day 21
Diffstat (limited to 'aoc-2022-dotnet')
-rw-r--r-- | aoc-2022-dotnet/Day21/Program.fs | 108 | ||||
-rw-r--r-- | aoc-2022-dotnet/README.md | 4 |
2 files changed, 71 insertions, 41 deletions
diff --git a/aoc-2022-dotnet/Day21/Program.fs b/aoc-2022-dotnet/Day21/Program.fs index 3837054..f9a608d 100644 --- a/aoc-2022-dotnet/Day21/Program.fs +++ b/aoc-2022-dotnet/Day21/Program.fs @@ -1,61 +1,91 @@ module Day21 open System.IO +open System.Numerics open FSharpPlus open FParsec open Common type MonkeyName = string -type Operator = int64 -> int64 -> int64 + +module MonkeyName = + let root = "root" + let human = "humn" + +type Operator = Complex -> Complex -> Complex + +module Operator = + let fromChar = + function + | '+' -> (+) + | '-' -> (-) + | '*' -> (*) + | '/' -> (/) + | c -> failwithf "Invalid operator: %c" c + + let unknownExtractor l r = + let eq: Complex = l - r + Complex(round <| -eq.Real / eq.Imaginary, 0) type MonkeyJob = - | Number of int64 + | Number of Complex | Operation of MonkeyName * Operator * MonkeyName + static member unknownVariable = Number(Complex(0, 1)) + + static member eval(cache: Map<MonkeyName, Complex>) = + function + | Number num -> num + | Operation (left, operator, right) -> operator cache[left] cache[right] + + static member withOperator op = + function + | Operation (l, _, r) -> Operation(l, op, r) + | other -> other + 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" +module Monkey = + let parse = + let pws = pchar ' ' + let pname = anyString 4 |>> MonkeyName + let pop = pws >>. anyChar .>> pws |>> Operator.fromChar + let pnumber = pfloat |>> (fun n -> Number(Complex(n, 0))) + let poperation = tuple3 pname pop pname |>> Operation + let pjob = pnumber <|> poperation + let pmonkey = pname .>> pstring ": " .>>. pjob |>> Monkey + Util.parse pmonkey + +let solution modification input = + let monkeys = + input + |> Seq.map Monkey.parse + |> Map.ofSeq + |> modification + + let nodeValues = + monkeys + |> Map.mapValues MonkeyJob.dependencies + |> Util.tsort + |> List.fold (fun cache name -> Map.add name (MonkeyJob.eval cache monkeys[name]) cache) Map.empty + + int64 nodeValues[MonkeyName.root].Real + +let part1 = id + +let part2 = + Map.add MonkeyName.human MonkeyJob.unknownVariable + >> Map.change MonkeyName.root (Option.map (MonkeyJob.withOperator Operator.unknownExtractor)) let test = File.ReadLines("test.txt") -assert (solution test = 152) +assert (solution part1 test = 152) +assert (solution part2 test = 301) let input = File.ReadLines("input.txt") -printfn "%d" <| solution input +printfn "%d" <| solution part1 input +printfn "%d" <| solution part2 input diff --git a/aoc-2022-dotnet/README.md b/aoc-2022-dotnet/README.md index bc6029a..37de967 100644 --- a/aoc-2022-dotnet/README.md +++ b/aoc-2022-dotnet/README.md @@ -1,6 +1,6 @@ # Advent of Code 2022 in F#  - + | Day | Problem Name | Part 1 | Part 2 | Practiced Concepts | | :----: | ---------------------------------------------------------------- | :----: | :----: | ---------------------------------------------------- | @@ -24,7 +24,7 @@ | **18** | [Boiling Boulders](https://adventofcode.com/2022/day/18) | :star: | :star: | functional DFS, 3D vectors, position bound checking | | **19** | [Not Enough Minerals](https://adventofcode.com/2022/day/19) | | | | | **20** | [Grove Positioning System](https://adventofcode.com/2022/day/20) | :star: | :star: | linked lists, modulo & remainder | -| **21** | [Monkey Math](https://adventofcode.com/2022/day/21) | | | | +| **21** | [Monkey Math](https://adventofcode.com/2022/day/21) | :star: | :star: | topological sort, ADTs, complex numbers | | **22** | [Monkey Map](https://adventofcode.com/2022/day/22) | | | | | **23** | [Unstable Diffusion](https://adventofcode.com/2022/day/23) | | | | | **24** | [Blizzard Basin](https://adventofcode.com/2022/day/24) | | | | |