aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--aoc-2022-dotnet/Day12/Program.fs2
-rw-r--r--aoc-2022-dotnet/Day16/Program.fs4
-rw-r--r--aoc-2022-dotnet/Day19/Day19.fsproj24
-rw-r--r--aoc-2022-dotnet/Day19/Program.fs148
-rw-r--r--aoc-2022-dotnet/Day21/Program.fs2
-rw-r--r--aoc-2022-dotnet/Day24/Program.fs2
-rw-r--r--aoc-2022-dotnet/README.md56
-rw-r--r--aoc-2022-dotnet/aoc-2022-dotnet.sln6
9 files changed, 212 insertions, 34 deletions
diff --git a/README.md b/README.md
index 13e3c15..010b263 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ Repository storing my solutions to Advent of Code. See other people's solutions
### [2022](aoc-2022-dotnet)
![F#](https://img.shields.io/badge/F%23-grey?logo=.NET)
-![Stars](https://img.shields.io/badge/🌟%20stars-45/50-orange)
+![Stars](https://img.shields.io/badge/🌟%20stars-47/50-orange)
[awesome]: https://github.com/Bogdanp/awesome-advent-of-code
[aoc]: https://adventofcode.com
diff --git a/aoc-2022-dotnet/Day12/Program.fs b/aoc-2022-dotnet/Day12/Program.fs
index 7e1a409..ccd7697 100644
--- a/aoc-2022-dotnet/Day12/Program.fs
+++ b/aoc-2022-dotnet/Day12/Program.fs
@@ -77,7 +77,7 @@ let solution distanceCalculation =
&& Square.canTraverse square (Util.mAt matrix np))
|> Set.map (Vec2.toIndexOf matrix)))
>> Seq.indexed
- >> Map.ofSeq
+ >> Map
>> Graph
>> distanceCalculation
>> Option.get
diff --git a/aoc-2022-dotnet/Day16/Program.fs b/aoc-2022-dotnet/Day16/Program.fs
index 87b0ffa..208d975 100644
--- a/aoc-2022-dotnet/Day16/Program.fs
+++ b/aoc-2022-dotnet/Day16/Program.fs
@@ -48,7 +48,7 @@ let buildGraph input =
bfsExplore Set.empty [] [ (start, 0) ]
- let valveMap = input |> Seq.map parseValve |> Map.ofSeq
+ let valveMap = input |> Seq.map parseValve |> Map
let flows =
valveMap
@@ -59,7 +59,7 @@ let buildGraph input =
valveMap
|> Map.keys
|> Seq.collect (distancesFrom valveMap)
- |> Map.ofSeq
+ |> Map
|> Map.filter (fun (f, t) _ ->
f <> t
&& Map.containsKey f flows
diff --git a/aoc-2022-dotnet/Day19/Day19.fsproj b/aoc-2022-dotnet/Day19/Day19.fsproj
new file mode 100644
index 0000000..d723b37
--- /dev/null
+++ b/aoc-2022-dotnet/Day19/Day19.fsproj
@@ -0,0 +1,24 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>net7.0</TargetFramework>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Content Include="test.txt">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </Content>
+ <Content Include="input.txt">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </Content>
+ <Compile Include="Program.fs" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Update="FSharp.Core">
+ <TreatAsUsed>true</TreatAsUsed>
+ </PackageReference>
+ </ItemGroup>
+
+</Project>
diff --git a/aoc-2022-dotnet/Day19/Program.fs b/aoc-2022-dotnet/Day19/Program.fs
new file mode 100644
index 0000000..e8770b6
--- /dev/null
+++ b/aoc-2022-dotnet/Day19/Program.fs
@@ -0,0 +1,148 @@
+module Day19
+
+open System
+open System.IO
+open System.Text.RegularExpressions
+
+type Resource =
+ | Ore
+ | Clay
+ | Obsidian
+ | Geode
+
+ static member list = [ Ore; Clay; Obsidian; Geode ]
+
+type State =
+ { Robots: Map<Resource, int>
+ Gathered: Map<Resource, int>
+ TimeLeft: int }
+
+ static member initial time =
+ { Robots =
+ Map [ (Ore, 1)
+ (Clay, 0)
+ (Obsidian, 0)
+ (Geode, 0) ]
+ Gathered =
+ Map [ (Ore, 0)
+ (Clay, 0)
+ (Obsidian, 0)
+ (Geode, 0) ]
+ TimeLeft = time }
+
+ member inline state.optimisticGeodeCount =
+ state.Gathered[Geode]
+ + state.Robots[Geode] * state.TimeLeft
+ + state.TimeLeft * (state.TimeLeft - 1) / 2
+
+ static member inline tick state =
+ { state with
+ Gathered = Map.map (fun resource -> (+) state.Robots[resource]) state.Gathered
+ TimeLeft = state.TimeLeft - 1 }
+
+ member inline state.isImpossibleToBuy =
+ function
+ | Geode -> state.Robots[Obsidian] = 0
+ | Obsidian -> state.Robots[Clay] = 0
+ | _ -> false
+
+type Blueprint =
+ { Id: int
+ RobotCosts: Map<Resource, Map<Resource, int>> }
+
+ static member private regex = Regex(@"\d+", RegexOptions.Compiled)
+
+ static member parse input =
+ Blueprint.regex.Matches(input)
+ |> Seq.map (fun kv -> int kv.Value)
+ |> List.ofSeq
+ |> function
+ | [ id; oreOreCost; clayOreCost; obsidianOreCost; obsidianClayCost; geodeOreCost; geodeObsidianCost ] ->
+ { Id = id
+ RobotCosts =
+ Map [ (Ore,
+ Map [ (Ore, oreOreCost)
+ (Clay, 0)
+ (Obsidian, 0)
+ (Geode, 0) ])
+ (Clay,
+ Map [ (Ore, clayOreCost)
+ (Clay, 0)
+ (Obsidian, 0)
+ (Geode, 0) ])
+ (Obsidian,
+ Map [ (Ore, obsidianOreCost)
+ (Clay, obsidianClayCost)
+ (Obsidian, 0)
+ (Geode, 0) ])
+ (Geode,
+ Map [ (Ore, geodeOreCost)
+ (Clay, 0)
+ (Obsidian, geodeObsidianCost)
+ (Geode, 0) ]) ] }
+ | _ -> failwith "Invalid blueprint format!"
+
+ member inline private blueprint.canBuyRobot robotResource state =
+ Map.forall (fun resource -> (>=) state.Gathered[resource]) blueprint.RobotCosts[robotResource]
+
+ member inline private blueprint.buyRobot robotResource state =
+ { state with
+ Robots = state.Robots.Change(robotResource, Option.map <| (+) 1)
+ Gathered =
+ state.Gathered
+ |> Map.map (fun costResource previousCount ->
+ previousCount
+ - blueprint.RobotCosts[robotResource][costResource]) }
+
+ static member private robotCaps blueprint =
+ Resource.list
+ |> List.map (fun costResource ->
+ costResource,
+ Resource.list
+ |> List.map (fun robotResource -> blueprint.RobotCosts[robotResource][costResource])
+ |> List.max)
+ |> Map.ofList
+ |> Map.add Geode Int32.MaxValue
+
+ static member evaluate time blueprint =
+ let robotCaps = Blueprint.robotCaps blueprint
+
+ let rec solve bestScore robotGoal state =
+ if state.TimeLeft <= 0 then
+ state.Gathered[Geode]
+ elif state.Robots[robotGoal] >= robotCaps[robotGoal]
+ || state.isImpossibleToBuy robotGoal
+ || state.optimisticGeodeCount <= bestScore then
+ bestScore
+ elif blueprint.canBuyRobot robotGoal state then
+ let state =
+ state
+ |> State.tick
+ |> blueprint.buyRobot robotGoal
+
+ List.fold (fun bestScore nextRobotGoal -> solve bestScore nextRobotGoal state) bestScore Resource.list
+ else
+ state |> State.tick |> solve bestScore robotGoal
+
+ List.fold (fun bestScore robotGoal -> solve bestScore robotGoal (State.initial time)) 0 Resource.list
+
+ static member inline qualityLevel blueprint =
+ blueprint.Id * Blueprint.evaluate 24 blueprint
+
+let solution1 =
+ Seq.map Blueprint.parse
+ >> Seq.sumBy Blueprint.qualityLevel
+
+let solution2 =
+ Seq.map Blueprint.parse
+ >> Seq.truncate 3
+ >> Seq.map (Blueprint.evaluate 32)
+ >> Seq.reduce (*)
+
+let test = File.ReadLines("test.txt")
+assert (solution1 test = 33)
+assert (solution2 test = 56 * 62)
+
+let input = File.ReadLines("input.txt")
+printfn "%d" <| solution1 input
+printfn "%d" <| solution2 input
diff --git a/aoc-2022-dotnet/Day21/Program.fs b/aoc-2022-dotnet/Day21/Program.fs
index f9a608d..6ca702c 100644
--- a/aoc-2022-dotnet/Day21/Program.fs
+++ b/aoc-2022-dotnet/Day21/Program.fs
@@ -65,7 +65,7 @@ let solution modification input =
let monkeys =
input
|> Seq.map Monkey.parse
- |> Map.ofSeq
+ |> Map
|> modification
let nodeValues =
diff --git a/aoc-2022-dotnet/Day24/Program.fs b/aoc-2022-dotnet/Day24/Program.fs
index 0446c06..2cb5ef8 100644
--- a/aoc-2022-dotnet/Day24/Program.fs
+++ b/aoc-2022-dotnet/Day24/Program.fs
@@ -19,7 +19,7 @@ type Valley =
Blizzards =
Vec2.directions4
|> Set.map (fun d -> d, Set.empty)
- |> Map.ofSeq }
+ |> Map }
static member private withExpeditionAt target valley =
{ valley with ExpeditionSuperposition = Set.singleton <| target valley }
diff --git a/aoc-2022-dotnet/README.md b/aoc-2022-dotnet/README.md
index 34d872f..2cf006d 100644
--- a/aoc-2022-dotnet/README.md
+++ b/aoc-2022-dotnet/README.md
@@ -1,31 +1,31 @@
# Advent of Code 2022 in F#
![F#](https://img.shields.io/badge/F%23-grey?logo=.NET)
-![Stars](https://img.shields.io/badge/🌟%20stars-45/50-orange)
+![Stars](https://img.shields.io/badge/🌟%20stars-47/50-orange)
-| Day | Problem Name | Part 1 | Part 2 | Practiced Concepts |
-| :----: | ---------------------------------------------------------------- | :----: | :----: | ---------------------------------------------------- |
-| **01** | [Calorie Counting](https://adventofcode.com/2022/day/1) | :star: | :star: | `Seq`, `\|>` and `>>`, FSharpPlus |
-| **02** | [Rock Paper Scissors](https://adventofcode.com/2022/day/2) | :star: | :star: | ADTs, type members, patterns |
-| **03** | [Rucksack Reorganization](https://adventofcode.com/2022/day/3) | :star: | :star: | ASCII code, `Set` |
-| **04** | [Camp Cleanup](https://adventofcode.com/2022/day/4) | :star: | :star: | ranges, FParsec |
-| **05** | [Supply Stacks](https://adventofcode.com/2022/day/5) | :star: | :star: | functional stacks, `List.transpose`, `Seq.fold` |
-| **06** | [Tuning Trouble](https://adventofcode.com/2022/day/6) | :star: | :star: | `Seq.windowed`, `Set` |
-| **07** | [No Space Left On Device](https://adventofcode.com/2022/day/7) | :star: | :star: | patterns, ADTs, FParsec |
-| **08** | [Treetop Tree House](https://adventofcode.com/2022/day/8) | :star: | :star: | `Array2D`, slices |
-| **09** | [Rope Bridge](https://adventofcode.com/2022/day/9) | :star: | :star: | 2D vectors, Chebyshev distance, `Seq.scan` |
-| **10** | [Cathode-Ray Tube](https://adventofcode.com/2022/day/10) | :star: | :star: | `Map`, `Seq.fold` |
-| **11** | [Monkey in the Middle](https://adventofcode.com/2022/day/11) | :star: | :star: | records, type abbrevs, `List.choose`, tail recursion |
-| **12** | [Hill Climbing Algorithm](https://adventofcode.com/2022/day/12) | :star: | :star: | functional graphs, functional BFS, `Array2D` |
-| **13** | [Distress Signal](https://adventofcode.com/2022/day/13) | :star: | :star: | `IComparable`, ADTs, patterns, FParsec |
-| **14** | [Regolith Reservoir](https://adventofcode.com/2022/day/14) | :star: | :star: | `Seq.unfold`, `Seq.pairwise`, functional DFS |
-| **15** | [Beacon Exclusion Zone](https://adventofcode.com/2022/day/15) | :star: | :star: | ranges, mahattan distance, parallel computing |
-| **16** | [Proboscidea Volcanium](https://adventofcode.com/2022/day/16) | :star: | :star: | graphs, dynamic programming, `Seq` |
-| **17** | [Pyroclastic Flow](https://adventofcode.com/2022/day/17) | :star: | :star: | cycle detection, bitwise operators, `hash` |
-| **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, remainder |
-| **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) | :star: | :star: | `Set`, 2D vectors, `Seq.unfold`, composition |
-| **24** | [Blizzard Basin](https://adventofcode.com/2022/day/24) | :star: | :star: | `Set`, 2D vectors, remainder, records |
-| **25** | [Full of Hot Air](https://adventofcode.com/2022/day/25) | :star: | | positional numeral systems, recursion |
+| Day | Problem Name | Part 1 | Part 2 | Practiced Concepts |
+| :----: | ---------------------------------------------------------------- | :----: | :----: | ----------------------------------------------------- |
+| **01** | [Calorie Counting](https://adventofcode.com/2022/day/1) | :star: | :star: | `Seq`, `\|>` and `>>`, FSharpPlus |
+| **02** | [Rock Paper Scissors](https://adventofcode.com/2022/day/2) | :star: | :star: | ADTs, type members, patterns |
+| **03** | [Rucksack Reorganization](https://adventofcode.com/2022/day/3) | :star: | :star: | ASCII code, `Set` |
+| **04** | [Camp Cleanup](https://adventofcode.com/2022/day/4) | :star: | :star: | ranges, FParsec |
+| **05** | [Supply Stacks](https://adventofcode.com/2022/day/5) | :star: | :star: | functional stacks, `List.transpose`, `Seq.fold` |
+| **06** | [Tuning Trouble](https://adventofcode.com/2022/day/6) | :star: | :star: | `Seq.windowed`, `Set` |
+| **07** | [No Space Left On Device](https://adventofcode.com/2022/day/7) | :star: | :star: | patterns, ADTs, FParsec |
+| **08** | [Treetop Tree House](https://adventofcode.com/2022/day/8) | :star: | :star: | `Array2D`, slices |
+| **09** | [Rope Bridge](https://adventofcode.com/2022/day/9) | :star: | :star: | 2D vectors, Chebyshev distance, `Seq.scan` |
+| **10** | [Cathode-Ray Tube](https://adventofcode.com/2022/day/10) | :star: | :star: | `Map`, `Seq.fold` |
+| **11** | [Monkey in the Middle](https://adventofcode.com/2022/day/11) | :star: | :star: | records, type abbrevs, `List.choose`, tail recursion |
+| **12** | [Hill Climbing Algorithm](https://adventofcode.com/2022/day/12) | :star: | :star: | functional graphs, functional BFS, `Array2D` |
+| **13** | [Distress Signal](https://adventofcode.com/2022/day/13) | :star: | :star: | `IComparable`, ADTs, patterns, FParsec |
+| **14** | [Regolith Reservoir](https://adventofcode.com/2022/day/14) | :star: | :star: | `Seq.unfold`, `Seq.pairwise`, functional DFS |
+| **15** | [Beacon Exclusion Zone](https://adventofcode.com/2022/day/15) | :star: | :star: | ranges, mahattan distance, parallel computing |
+| **16** | [Proboscidea Volcanium](https://adventofcode.com/2022/day/16) | :star: | :star: | graphs, dynamic programming, `Seq` |
+| **17** | [Pyroclastic Flow](https://adventofcode.com/2022/day/17) | :star: | :star: | cycle detection, bitwise operators, `hash` |
+| **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) | :star: | :star: | `List.fold`, records, `Map`, mutability, optimization |
+| **20** | [Grove Positioning System](https://adventofcode.com/2022/day/20) | :star: | :star: | linked lists, remainder |
+| **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) | :star: | :star: | `Set`, 2D vectors, `Seq.unfold`, composition |
+| **24** | [Blizzard Basin](https://adventofcode.com/2022/day/24) | :star: | :star: | `Set`, 2D vectors, remainder, records |
+| **25** | [Full of Hot Air](https://adventofcode.com/2022/day/25) | :star: | | positional numeral systems, recursion |
diff --git a/aoc-2022-dotnet/aoc-2022-dotnet.sln b/aoc-2022-dotnet/aoc-2022-dotnet.sln
index a233bf2..5d1708a 100644
--- a/aoc-2022-dotnet/aoc-2022-dotnet.sln
+++ b/aoc-2022-dotnet/aoc-2022-dotnet.sln
@@ -60,6 +60,8 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Day23", "Day23\Day23.fsproj
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Day24", "Day24\Day24.fsproj", "{253313A4-C9F8-4A83-89A5-8FCB426004E0}"
EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Day19", "Day19\Day19.fsproj", "{65ED4E60-D36D-4519-9DF1-EFCE6787D480}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -166,6 +168,10 @@ Global
{253313A4-C9F8-4A83-89A5-8FCB426004E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{253313A4-C9F8-4A83-89A5-8FCB426004E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{253313A4-C9F8-4A83-89A5-8FCB426004E0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {65ED4E60-D36D-4519-9DF1-EFCE6787D480}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {65ED4E60-D36D-4519-9DF1-EFCE6787D480}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {65ED4E60-D36D-4519-9DF1-EFCE6787D480}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {65ED4E60-D36D-4519-9DF1-EFCE6787D480}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE