From b6de2b46883bd4b146da89f3aad065b6c46743ac Mon Sep 17 00:00:00 2001 From: Smaug123 Date: Sun, 10 Dec 2023 13:28:33 +0000 Subject: [PATCH] Day 10 part 2 --- .../AdventOfCode2023.FSharp.Lib/Day10.fs | 178 +++++++++++++++++- AdventOfCode2023.FSharp/Test/Test.fsproj | 2 +- AdventOfCode2023.FSharp/Test/TestDay10.fs | 2 +- 3 files changed, 179 insertions(+), 3 deletions(-) diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day10.fs b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day10.fs index ed199ec..179535f 100644 --- a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day10.fs +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day10.fs @@ -129,5 +129,181 @@ module Day10 = distance + let floodFill (stackBuf : ResizeArray<_>) (s : Arr2D) (currX : int) (currY : int) = + stackBuf.Clear () + stackBuf.Add (currX, currY) + while stackBuf.Count > 0 do + let currX, currY = 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, 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, currY)) + if currY > 0 then + if Arr2D.get s currX (currY - 1) = 0uy then + Arr2D.set s currX (currY - 1) 2uy + stackBuf.Add ((currX, 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, currY + 1)) + + let print (s : Arr2D) = + for y = 0 to s.Height - 1 do + for x = 0 to s.Width - 1 do + match Arr2D.get s x y with + | 0uy -> printf " " + | 1uy -> printf "#" + | 2uy -> printf "." + | s -> failwithf "unrecognised: %i" s + printfn "" + + printfn "" + printfn "" + + let inline setAt (arr : Arr2D) (x : int) (y : int) (matching : char) (target : byte) = + Arr2D.set arr x y target + match matching with + | '-' -> + Arr2D.set arr (x - 1) y target + Arr2D.set arr (x + 1) y target + | '|' -> + Arr2D.set arr x (y - 1) target + Arr2D.set arr x (y + 1) target + | 'L' -> + Arr2D.set arr x (y - 1) target + Arr2D.set arr (x + 1) y target + | 'J' -> + Arr2D.set arr x (y - 1) target + Arr2D.set arr (x - 1) y target + | '7' -> + Arr2D.set arr x (y + 1) target + Arr2D.set arr (x - 1) y target + | 'F' -> + Arr2D.set arr x (y + 1) target + Arr2D.set arr (x + 1) y target + | c -> failwithf "bad char: %c" c + let part2 (s : string) = - 0 + let s = s.AsSpan() + let lineCount = s.Count '\n' + let lineLength = (s.IndexOf '\n' + 1) + let startPos = s.IndexOf 'S' + + let buffer = Array.zeroCreate (lineCount * lineLength * 9) +#if DEBUG + let system : Arr2D = + { + Elements = buffer + Width = 3 * lineLength + } +#else + use ptr = fixed buffer + let system : Arr2D = + { Elements = ptr + Length = buffer.Length + Width = 3 * lineLength + } +#endif + + let struct (startLine, startCol) = toRowAndCol lineLength lineCount startPos + let mutable prevPointA = startPos + let mutable prevPointB = startPos + + Arr2D.set system (3 * startCol + 1) (3 * startLine + 1) 1uy + + let mutable pointA = + let pos = ofRowAndCol lineLength lineCount startLine (startCol - 1) + match if pos >= 0 then s.[pos] else 'n' with + | '-' + | 'L' + | 'F' -> + Arr2D.set system (3 * startCol) (3 * startLine + 1) 1uy + pos + | _ -> + + let pos = ofRowAndCol lineLength lineCount startLine (startCol + 1) + match if pos < s.Length then s.[pos] else 'n' with + | '-' + | 'J' + | '7' -> + Arr2D.set system (3 * startCol + 2) (3 * startLine + 1) 1uy + pos + | _ -> + + Arr2D.set system (3 * startCol) (3 * startLine) 1uy + Arr2D.set system (3 * startCol) (3 * startLine + 2) 1uy + ofRowAndCol lineLength lineCount (startLine + 1) startCol + + let mutable pointB = + let pos = ofRowAndCol lineLength lineCount (startLine - 1) startCol + match if pos >= 0 then s.[pos] else 'n' with + | '|' + | '7' + | 'F' -> + Arr2D.set system (3 * startCol + 1) (3 * startLine) 1uy + pos + | _ -> + + let pos = ofRowAndCol lineLength lineCount (startLine + 1) startCol + match if pos < s.Length then s.[pos] else 'n' with + | '|' + | 'L' + | 'J' -> + Arr2D.set system (3 * startCol + 1) (3 * startLine + 2) 1uy + pos + | _ -> + + let pos = ofRowAndCol lineLength lineCount startLine (startCol + 1) + match if pos < s.Length then s.[pos] else 'n' with + | '-' + | 'J' + | '7' -> + Arr2D.set system (3 * startCol + 2) (3 * startLine + 1) 1uy + pos + | _ -> + ofRowAndCol lineLength lineCount startLine (startCol - 1) + + do + let struct (row, col) = toRowAndCol lineLength lineCount pointA + setAt system (3 * col + 1) (3 * row + 1) s.[pointA] 1uy + do + let struct (row, col) = toRowAndCol lineLength lineCount pointB + setAt system (3 * col + 1) (3 * row + 1) s.[pointB] 1uy + + while pointA <> pointB do + let currentA = pointA + pointA <- nextPoint s lineLength lineCount pointA prevPointA + prevPointA <- currentA + do + let struct (row, col) = toRowAndCol lineLength lineCount pointA + setAt system (3 * col + 1) (3 * row + 1) s.[pointA] 1uy + + let currentB = pointB + pointB <- nextPoint s lineLength lineCount pointB prevPointB + prevPointB <- currentB + do + let struct (row, col) = toRowAndCol lineLength lineCount pointB + setAt system (3 * col + 1) (3 * row + 1) s.[pointB] 1uy + + let stackBuf = ResizeArray () + for line = 0 to system.Height - 1 do + floodFill stackBuf system 0 line + floodFill stackBuf system (system.Width - 1) line + for col = 0 to system.Width - 1 do + floodFill stackBuf system col 0 + floodFill stackBuf system col (system.Height - 1) + + let mutable answer = 0 + + for row = 0 to lineCount - 1 do + for col = 0 to lineLength - 1 do + if Arr2D.get system (3 * col + 1) (3 * row + 1) = 0uy then + answer <- answer + 1 + + answer diff --git a/AdventOfCode2023.FSharp/Test/Test.fsproj b/AdventOfCode2023.FSharp/Test/Test.fsproj index 4cef56b..b511fbe 100644 --- a/AdventOfCode2023.FSharp/Test/Test.fsproj +++ b/AdventOfCode2023.FSharp/Test/Test.fsproj @@ -31,7 +31,7 @@ - + diff --git a/AdventOfCode2023.FSharp/Test/TestDay10.fs b/AdventOfCode2023.FSharp/Test/TestDay10.fs index 99ee5b7..b0205c2 100644 --- a/AdventOfCode2023.FSharp/Test/TestDay10.fs +++ b/AdventOfCode2023.FSharp/Test/TestDay10.fs @@ -99,4 +99,4 @@ L--J.L7...LJS7F-7L7. Assert.Inconclusive () failwith "unreachable" - Day10.part2 s |> shouldEqual -1 + Day10.part2 s |> shouldEqual 393