Compare commits

1 Commits

Author SHA1 Message Date
e2d5e6bafc add quest 3 2025-12-01 14:45:23 +01:00
6 changed files with 133 additions and 4 deletions

View File

@@ -31,9 +31,22 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Inputs\Quest03\Q03_P01.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Inputs\Quest03\Q03_P02.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Inputs\Quest03\Q03_P03.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Compile Include="Helpers.fs" />
<Compile Include="Quest01.fs" />
<Compile Include="Quest02.fs" />
<Compile Include="Quest03.fs" />
<Compile Include="Program.fs"/>
</ItemGroup>

View File

@@ -0,0 +1 @@
8,55,7,42,40,45,33,31,64,60,49,66,83,78,33,23,72,15,35,11,84,30,44,66,20,66,88,7,3,51,85,54,38,88,2,37,2,56,47,40,82,79,51,18,81,69,46,52,56,5,82,73,15,76,13,11,31,43,50,89,79,85,11,44,26,6,12,49,82,28,66,36,66,22,44,39,2,39,83,15,63,82,10,73,20,64,17,25,43,72,54,47,30,15,46,87,85,17,57,6

View File

@@ -0,0 +1 @@
88,59,145,183,26,132,49,153,120,180,134,184,132,6,29,57,137,105,166,61,105,49,10,55,149,145,165,88,56,140,78,78,167,84,82,22,21,185,63,38,65,55,140,27,109,104,156,101,156,7,145,30,127,88,145,44,113,142,14,60,77,92,147,76,74,189,104,186,100,175,118,104,94,182,7,52,110,12,132,18,123,161,148,174,150,18,66,107,179,81,178,26,136,23,92,95,10,10,34,4,134,138,107,12,27,26,76,77,31,44,113,17,54,31,71,22,63,172,145,65,138,47,119,56,50,40,162,150,56,85,65,27,4,172,113,26,59,104,86,158,67,93,134,47,178,115,3,7,24,70,53,159,170,183,165,129,92,36,104,110,120,8,2,133,60,118,181,70,132,67,180,133,185,111,107,93,10,19,154,185,29,144,79,3,14,5,15,132,179,18,77,140,68,20,109,43,36,115,77,83,49,80,189,120,6,152,16,98,144,171,83,88,165,6,52,157,102,119,158,127,138,11,48,142,21,159,55,173,45,176,9,141,109,44,36,166,143,144,138,134,86,129,106,80,41,100,56,143,125,73,94,86,51,137,29,75,107,117,110,145,161,70,180,26,45,146,123,150,28,68,6,148,40,84,134,121,113,29,148,19,174,140,147,147,94,98,18,149,59,156,22,83,40,145,180,86,44,3,118,26

File diff suppressed because one or more lines are too long

View File

@@ -1,14 +1,14 @@
// For more information see https://aka.ms/fsharp-console-apps
open EveryBodyCodes2025
open Quest03
[<EntryPoint>]
let main argv =
try
printfn $"{Quest02.part1()}"
printfn $"{part1()}"
//Quest02.test1
printfn $"{Quest02.part2()}"
printfn $"{Quest02.part3()}"
printfn $"{part2()}"
printfn $"{part3()}"
with exn ->
printfn $"{exn}"
0

View File

@@ -0,0 +1,113 @@
module EveryBodyCodes2025.Quest03
open System.Collections.Generic
open System.IO
open System.Linq
open System
open System.Runtime.CompilerServices
type Crate = int
// sorted set because only one item can be in at a time. The SortedSet is unnecessary here since the inputs are already sorted
type CrateSet = SortedSet<Crate>
let inline newCrateSet crate =
let cs = CrateSet()
cs.Add(crate) |> ignore
cs
type Extensions() =
[<Extension>]
static member inline SmallestCrate (crates:CrateSet) : Crate option = match crates.Min with | 0 -> None | x -> Some x
[<Extension>]
static member inline LargestCrate (crates:CrateSet) : Crate option = match crates.Max with | 0 -> None | x -> Some x
/// take a sorted input (not verified) and prioritize insertion into the first found list.
/// This results in cascading to the "next best fit", but this approach relies on sorted inputs.
let packEfficiently allCrates =
allCrates
|> Seq.fold (fun sortedCrates next ->
// find the first crate set that can hold the next item and put it in there
match sortedCrates with
| [] -> [newCrateSet next]
| items ->
match List.tryFind (fun (i:CrateSet) ->
match i.SmallestCrate() with
| Some c when c > next -> true
| _ -> false) items with
| None ->
let cs = newCrateSet next
items@[cs] // appending to the end is less efficient for linked lists, but ensures that the first one gets the best goodies
| Some crates ->
if not (crates.Add(next)) then failwith "failed to add" // really wrong if this happens
items
) []
let parseInput file =
File.ReadLines(file)
|> Enumerable.First
|> _.Split(",")
|> Array.map Int32.Parse
let part1Test() =
"10,5,1,10,3,8,5,2,2"
|> _.Split(",")
|> Array.map Int32.Parse
|> Enumerable.OrderDescending
|> packEfficiently
|> _.Max(_.Sum())
let part1 () =
parseInput "Inputs/Quest03/Q03_P01.txt"
|> Enumerable.OrderDescending
|> packEfficiently
|> _.Max(_.Sum())
// Part 2 I thought would be better to invert the sorting (asc vs desc) to part 1. It also adds an add filter to 20 items.
let part2Impl allCrates =
allCrates
|> Seq.fold (fun sortedCrates next ->
//smallest set of max size - sort ascending, add up until there are 20 items, then it is not eligible
match sortedCrates with
| [] ->
let cs = CrateSet()
cs.Add(next) |> ignore
[cs]
| items ->
match List.tryFind (fun (i:CrateSet) ->
if i.Count >= 20 then false
else
match i.LargestCrate() with
| Some c when c < next -> true
| _ -> false) items with
| None ->
let cs = CrateSet()
match cs.Add(next) with | true -> () | false -> failwith "failed to add"
items@[cs]
| Some crates ->
match crates.Add(next) with | true -> () | false -> failwith "failed to add"
items
) []
let part2Test() =
"4,51,13,64,57,51,82,57,16,88,89,48,32,49,49,2,84,65,49,43,9,13,2,3,75,72,63,48,61,14,40,77"
|> _.Split(",")
|> Array.map Int32.Parse
|> Enumerable.Order
|> part2Impl
|> List.filter (fun x -> x.Count = 20)
|> _.Min(_.Sum())
let part2() =
parseInput "Inputs/Quest03/Q03_P02.txt"
|> Enumerable.Order
|> part2Impl
|> List.filter (fun x -> x.Count = 20)
|> _.Min(_.Sum())
let part3() =
parseInput "Inputs/Quest03/Q03_P03.txt"
|> Enumerable.OrderDescending
|> packEfficiently
|> _.Count()