From 2f871fa83ac561bd7ca97bdc58ac5395b6daa6e1 Mon Sep 17 00:00:00 2001 From: Smaug123 Date: Fri, 15 Dec 2023 10:35:35 +0000 Subject: [PATCH] Day 15 --- .../AdventOfCode2023.FSharp.Lib/Day15.fs | 79 ++++++++++++++++++- AdventOfCode2023.FSharp/Test/TestDay15.fs | 8 +- .../Test/samples/day15.txt | 1 + 3 files changed, 82 insertions(+), 6 deletions(-) diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day15.fs b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day15.fs index d7a9d7b..0aba77d 100644 --- a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day15.fs +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day15.fs @@ -1,11 +1,86 @@ namespace AdventOfCode2023 open System +open System.Globalization [] module Day15 = + + let hash (s : ReadOnlySpan) : int = + let mutable v = 0 + + for c in s do + v <- v + int (byte c) + v <- (17 * v) % 256 + + v + let part1 (s : string) = - 0 + let s = s.AsSpan().TrimEnd () + use chunks = StringSplitEnumerator.make' ',' s + let mutable answer = 0 + + for chunk in chunks do + answer <- answer + hash chunk + + answer + + let removeFirst<'a> (toRemove : 'a -> bool) (arr : ResizeArray<'a>) : unit = + let mutable i = 0 + + while i < arr.Count do + if toRemove arr.[i] then + for j = i to arr.Count - 2 do + arr.[j] <- arr.[j + 1] + + arr.RemoveAt (arr.Count - 1) + i <- arr.Count + + i <- i + 1 + + let replace (withKey : 'a -> 'key) (key : 'key) (value : 'a) (arr : ResizeArray<'a>) : unit = + let mutable i = 0 + + while i < arr.Count do + if withKey arr.[i] = key then + arr.[i] <- value + i <- arr.Count + + i <- i + 1 + + if i < arr.Count + 1 then + // no replacement was made + arr.Add value + + let inline focusingPower (boxNumber : int) (arr : ResizeArray<_ * _>) : int = + let mutable answer = 0 + + for i = 0 to arr.Count - 1 do + answer <- answer + (boxNumber + 1) * (i + 1) * snd arr.[i] + + answer let part2 (s : string) = - 0 + let s = s.AsSpan().TrimEnd () + use chunks = StringSplitEnumerator.make' ',' s + let lenses = Array.init 256 (fun _ -> ResizeArray ()) + + for chunk in chunks do + if chunk.[chunk.Length - 1] = '-' then + let label = chunk.Slice(0, chunk.Length - 1).ToString () + removeFirst (fun (label2, _focalLength) -> label2 = label) lenses.[hash (label.AsSpan ())] + else + let equalsPos = chunk.IndexOf '=' + + let focalLength = + Int32.Parse (chunk.Slice (equalsPos + 1), NumberStyles.None, CultureInfo.InvariantCulture) + + let label = chunk.Slice(0, equalsPos).ToString () + replace fst label (label, focalLength) lenses.[hash (label.AsSpan ())] + + let mutable answer = 0 + + for i = 0 to 255 do + answer <- answer + focusingPower i lenses.[i] + + answer diff --git a/AdventOfCode2023.FSharp/Test/TestDay15.fs b/AdventOfCode2023.FSharp/Test/TestDay15.fs index 0cfb73e..48e9758 100644 --- a/AdventOfCode2023.FSharp/Test/TestDay15.fs +++ b/AdventOfCode2023.FSharp/Test/TestDay15.fs @@ -15,11 +15,11 @@ module TestDay15 = [] let part1Sample () = - sample |> Day15.part1 |> shouldEqual -1 + sample |> Day15.part1 |> shouldEqual 1320 [] let part2Sample () = - sample |> Day15.part2 |> shouldEqual -1 + sample |> Day15.part2 |> shouldEqual 145 [] let part1Actual () = @@ -32,7 +32,7 @@ module TestDay15 = Assert.Inconclusive () failwith "unreachable" - Day15.part1 s |> shouldEqual -1 + Day15.part1 s |> shouldEqual 521434 [] let part2Actual () = @@ -45,4 +45,4 @@ module TestDay15 = Assert.Inconclusive () failwith "unreachable" - Day15.part2 s |> shouldEqual -1 + Day15.part2 s |> shouldEqual 248279 diff --git a/AdventOfCode2023.FSharp/Test/samples/day15.txt b/AdventOfCode2023.FSharp/Test/samples/day15.txt index e69de29..4f58f74 100644 --- a/AdventOfCode2023.FSharp/Test/samples/day15.txt +++ b/AdventOfCode2023.FSharp/Test/samples/day15.txt @@ -0,0 +1 @@ +rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7