diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/AdventOfCode2023.FSharp.Lib.fsproj b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/AdventOfCode2023.FSharp.Lib.fsproj index df4939d..7acefda 100644 --- a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/AdventOfCode2023.FSharp.Lib.fsproj +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/AdventOfCode2023.FSharp.Lib.fsproj @@ -1,4 +1,4 @@ - + net8.0 @@ -13,6 +13,7 @@ + diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Arr2D.fs b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Arr2D.fs index 514292f..656f3c9 100644 --- a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Arr2D.fs +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Arr2D.fs @@ -5,6 +5,7 @@ #nowarn "9" #endif +open System open Microsoft.FSharp.NativeInterop [] @@ -100,3 +101,76 @@ module Arr2D = #else NativePtr.initBlock a.Elements 0uy (uint32 sizeof<'a> * uint32 a.Length) #endif + + /// Pass in a buffer of memory which we will use entirely for our own purposes (and may resize) + /// to maintain state. + /// `empty` is the value in empty cells; we will fill them with `fillWith`. + let floodFill + (stackBuf : ResizeArray) + (s : Arr2D<'a>) + (empty : 'a) + (fillWith : 'a) + (currX : int) + (currY : int) + : unit + = + stackBuf.Clear () + stackBuf.Add currX + stackBuf.Add currY + + while stackBuf.Count > 0 do + let currY = stackBuf.[stackBuf.Count - 1] + stackBuf.RemoveAt (stackBuf.Count - 1) + let currX = stackBuf.[stackBuf.Count - 1] + stackBuf.RemoveAt (stackBuf.Count - 1) + + if currX > 0 then + if get s (currX - 1) currY = empty then + set s (currX - 1) currY fillWith + stackBuf.Add (currX - 1) + stackBuf.Add currY + + if currX < s.Width - 1 then + if get s (currX + 1) currY = empty then + set s (currX + 1) currY fillWith + stackBuf.Add (currX + 1) + stackBuf.Add currY + + if currY > 0 then + if get s currX (currY - 1) = empty then + set s currX (currY - 1) fillWith + stackBuf.Add currX + stackBuf.Add (currY - 1) + + if currY < s.Height - 1 then + if get s currX (currY + 1) = empty then + set s currX (currY + 1) fillWith + stackBuf.Add currX + stackBuf.Add (currY + 1) + + /// SIMD go brr + let inline count< ^a when 'a : equality and 'a : unmanaged and 'a :> IEquatable<'a>> + (arr : Arr2D<'a>) + (x : 'a) + : int + = + let span = +#if DEBUG + arr.Elements.AsSpan () +#else + ReadOnlySpan<'a> (NativePtr.toVoidPtr arr.Elements, arr.Length) +#endif + MemoryExtensions.Count (span, x) + + let print (arr : Arr2D) = + for row = 0 to arr.Height - 1 do + for col = 0 to arr.Width - 1 do + match get arr col row with + | 1uy -> printf "#" + | 0uy -> printf "." + | 2uy -> printf "O" + | _ -> failwith "bad" + + printfn "" + + printfn "" diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day10.fs b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day10.fs index 637373e..1c1ab18 100644 --- a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day10.fs +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day10.fs @@ -123,41 +123,6 @@ module Day10 = distance - let floodFill (stackBuf : ResizeArray<_>) (s : Arr2D) (currX : int) (currY : int) = - stackBuf.Clear () - stackBuf.Add currX - stackBuf.Add currY - - while stackBuf.Count > 0 do - let currY = stackBuf.[stackBuf.Count - 1] - stackBuf.RemoveAt (stackBuf.Count - 1) - let currX = stackBuf.[stackBuf.Count - 1] - stackBuf.RemoveAt (stackBuf.Count - 1) - - if currX > 0 then - if Arr2D.get s (currX - 1) currY = 0uy then - Arr2D.set s (currX - 1) currY 2uy - stackBuf.Add (currX - 1) - stackBuf.Add currY - - if currX < s.Width - 1 then - if Arr2D.get s (currX + 1) currY = 0uy then - Arr2D.set s (currX + 1) currY 2uy - stackBuf.Add (currX + 1) - stackBuf.Add currY - - if currY > 0 then - if Arr2D.get s currX (currY - 1) = 0uy then - Arr2D.set s currX (currY - 1) 2uy - stackBuf.Add currX - stackBuf.Add (currY - 1) - - if currY < s.Height - 1 then - if Arr2D.get s currX (currY + 1) = 0uy then - Arr2D.set s currX (currY + 1) 2uy - stackBuf.Add currX - stackBuf.Add (currY + 1) - let print (s : Arr2D) = for y = 0 to s.Height - 1 do for x = 0 to s.Width - 1 do @@ -310,12 +275,12 @@ module Day10 = let stackBuf = ResizeArray () for line = 0 to system.Height - 1 do - floodFill stackBuf system 0 line - floodFill stackBuf system (system.Width - 1) line + Arr2D.floodFill stackBuf system 0uy 2uy 0 line + Arr2D.floodFill stackBuf system 0uy 2uy (system.Width - 1) line for col = 0 to system.Width - 1 do - floodFill stackBuf system col 0 - floodFill stackBuf system col (system.Height - 1) + Arr2D.floodFill stackBuf system 0uy 2uy col 0 + Arr2D.floodFill stackBuf system 0uy 2uy col (system.Height - 1) let mutable answer = 0 diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day14.fs b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day14.fs index 3631a35..cf1426d 100644 --- a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day14.fs +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day14.fs @@ -137,19 +137,6 @@ module Day14 = else // current = 0uy pos <- pos + 1 - let print (board : Arr2D) = - for row = 0 to board.Height - 1 do - for col = 0 to board.Width - 1 do - match Arr2D.get board col row with - | 0uy -> printf "." - | 1uy -> printf "O" - | 2uy -> printf "#" - | _ -> failwith "bad value" - - printfn "" - - printfn "" - let score (board : Arr2D) = let mutable answer = 0ul diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day16.fs b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day16.fs index a44c8c3..24df0d9 100644 --- a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day16.fs +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day16.fs @@ -10,22 +10,8 @@ open System [] module Day16 = - type Direction = - | Left = 0 - | Right = 1 - | Up = 2 - | Down = 3 - - let inline dirToInt (d : Direction) = - match d with - | Direction.Left -> 0us - | Direction.Right -> 1us - | Direction.Up -> 2us - | Direction.Down -> 3us - | _ -> failwith "Bad" - let inline storeDirectionAndPos (numCols : int) (col : int) (row : int) (direction : Direction) : uint16 = - 4us * uint16 (col + numCols * row) + dirToInt direction + 4us * uint16 (col + numCols * row) + Direction.toUInt direction let inline getDirection (input : uint16) = match input % 4us with diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Direction.fs b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Direction.fs new file mode 100644 index 0000000..52ae655 --- /dev/null +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Direction.fs @@ -0,0 +1,24 @@ +namespace AdventOfCode2023 + +type Direction = + | Left = 0 + | Right = 1 + | Up = 2 + | Down = 3 + +module Direction = + let inline toUInt (d : Direction) = + match d with + | Direction.Left -> 0us + | Direction.Right -> 1us + | Direction.Up -> 2us + | Direction.Down -> 3us + | _ -> failwith "Bad" + + let inline ofChar (c : char) : Direction = + match c with + | 'L' -> Direction.Left + | 'R' -> Direction.Right + | 'U' -> Direction.Up + | 'D' -> Direction.Down + | c -> failwith $"Bad: %c{c}"