diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day12.fs b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day12.fs index df5bb30..3ac1f18 100644 --- a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day12.fs +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day12.fs @@ -8,38 +8,51 @@ open System.Globalization module Day12 = let rec solve (line : ReadOnlySpan) (groups : IReadOnlyList) (currentGroupIndex : int) = + if line.Length = 0 then + if currentGroupIndex = groups.Count then LanguagePrimitives.GenericOne else LanguagePrimitives.GenericZero + else match line.[0] with | '#' -> - if currentGroupIndex >= groups.Count then 0 else + if currentGroupIndex >= groups.Count then LanguagePrimitives.GenericZero else let mutable isOk = true for i = 1 to groups.[currentGroupIndex] - 1 do - if isOk && line.[i] <> '#' && line.[i] <> '?' then + if isOk && (i >= line.Length || (line.[i] <> '#' && line.[i] <> '?')) then isOk <- false - if not isOk then 0 else - if line.[groups.[currentGroupIndex]] = '#' then 0 else - solve (line.Slice (groups.[currentGroupIndex] + 1)) groups (currentGroupIndex + 1) + if not isOk then LanguagePrimitives.GenericZero else + if groups.[currentGroupIndex] < line.Length then + if line.[groups.[currentGroupIndex]] = '#' then + LanguagePrimitives.GenericZero + else + solve (line.Slice (groups.[currentGroupIndex] + 1)) groups (currentGroupIndex + 1) + else + solve ReadOnlySpan<_>.Empty groups (currentGroupIndex + 1) | '.' -> solve (line.Slice 1) groups currentGroupIndex | '?' -> let ifDot = solve (line.Slice 1) groups currentGroupIndex let ifHash = - if currentGroupIndex >= groups.Count then 0 else + if currentGroupIndex >= groups.Count then LanguagePrimitives.GenericZero else let mutable isOk = true for i = 1 to groups.[currentGroupIndex] - 1 do - if isOk && line.[i] <> '#' && line.[i] <> '?' then + if isOk && (i >= line.Length || (line.[i] <> '#' && line.[i] <> '?')) then isOk <- false - if not isOk then 0 else - if line.[groups.[currentGroupIndex]] = '#' then 0 else - solve (line.Slice (groups.[currentGroupIndex] + 1)) groups (currentGroupIndex + 1) + if not isOk then LanguagePrimitives.GenericZero else + if groups.[currentGroupIndex] < line.Length then + if groups.[currentGroupIndex] < line.Length && line.[groups.[currentGroupIndex]] = '#' then + LanguagePrimitives.GenericZero + else + solve (line.Slice (groups.[currentGroupIndex] + 1)) groups (currentGroupIndex + 1) + else + solve ReadOnlySpan<_>.Empty groups (currentGroupIndex + 1) ifDot + ifHash | _ -> - if currentGroupIndex = groups.Count then 1 else 0 + if currentGroupIndex = groups.Count then LanguagePrimitives.GenericOne else LanguagePrimitives.GenericZero let part1 (s : string) = use mutable lines = StringSplitEnumerator.make '\n' s - let mutable answer = 0 + let mutable answer = 0uL let arr = ResizeArray () for line in lines do if not line.IsEmpty then @@ -56,4 +69,22 @@ module Day12 = let part2 (s : string) = use mutable lines = StringSplitEnumerator.make '\n' s - -1 + let mutable answer = 0uL + let arr = ResizeArray () + for line in lines do + if not line.IsEmpty then + arr.Clear () + let spaceIndex =line.IndexOf ' ' + for _ = 0 to 4 do + use ints = StringSplitEnumerator.make' ',' (line.Slice (spaceIndex + 1)) + for int in ints do + arr.Add (Int32.Parse (int, NumberStyles.None, CultureInfo.InvariantCulture)) + + let sliced = line.Slice(0, spaceIndex).ToString () + let line = String.Concat (sliced, '?', sliced, '?', sliced, '?', sliced, '?', sliced) + + let solved = solve (line.AsSpan()) arr 0 + printfn $"%s{line} : %i{solved}" + answer <- answer + solved + + answer diff --git a/AdventOfCode2023.FSharp/Test/TestDay12.fs b/AdventOfCode2023.FSharp/Test/TestDay12.fs index 30d412c..3245ade 100644 --- a/AdventOfCode2023.FSharp/Test/TestDay12.fs +++ b/AdventOfCode2023.FSharp/Test/TestDay12.fs @@ -12,13 +12,13 @@ module TestDay12 = [] let part1Sample () = - sample |> Day12.part1 |> shouldEqual 21 + sample |> Day12.part1 |> shouldEqual 21uL [] let part2Sample () = sample |> Day12.part2 - |> shouldEqual 0 + |> shouldEqual 525152uL [] let part1Actual () = @@ -31,7 +31,7 @@ module TestDay12 = Assert.Inconclusive () failwith "unreachable" - Day12.part1 s |> shouldEqual 7402 + Day12.part1 s |> shouldEqual 7402uL [] let part2Actual () = @@ -44,4 +44,4 @@ module TestDay12 = Assert.Inconclusive () failwith "unreachable" - Day12.part2 s |> shouldEqual 0 + Day12.part2 s |> shouldEqual 0uL