diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/AdventOfCode2023.FSharp.Lib.fsproj b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/AdventOfCode2023.FSharp.Lib.fsproj index d0848ee..270bd11 100644 --- a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/AdventOfCode2023.FSharp.Lib.fsproj +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/AdventOfCode2023.FSharp.Lib.fsproj @@ -9,6 +9,7 @@ + diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day2.fs b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day2.fs new file mode 100644 index 0000000..4ff87e8 --- /dev/null +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day2.fs @@ -0,0 +1,61 @@ +namespace AdventOfCode2023 + +open System + +[] +module Day2 = + + let part1 (s : string) = + use lines = StringSplitEnumerator.make '\n' s + let mutable answer = 0 + + for line in lines do + if not line.IsEmpty then + use mutable words = StringSplitEnumerator.make' ' ' line + let mutable prevWord = ReadOnlySpan.Empty + let mutable isOk = true + + while isOk && words.MoveNext () do + match words.Current.[0] with + | 'b' -> + if Int32.Parse prevWord > 14 then + isOk <- false + | 'r' -> + if Int32.Parse prevWord > 12 then + isOk <- false + | 'g' -> + if Int32.Parse prevWord > 13 then + isOk <- false + | _ -> () + + prevWord <- words.Current + + if isOk then + answer <- answer + Int32.Parse (line.Slice (5, line.IndexOf ':' - 5)) + + answer + + let part2 (s : string) = + use lines = StringSplitEnumerator.make '\n' s + let mutable answer = 0 + + for line in lines do + if not line.IsEmpty then + let mutable reds = 0 + let mutable blues = 0 + let mutable greens = 0 + use mutable words = StringSplitEnumerator.make' ' ' line + let mutable prevWord = ReadOnlySpan.Empty + + while words.MoveNext () do + match words.Current.[0] with + | 'b' -> blues <- max blues (Int32.Parse prevWord) + | 'r' -> reds <- max reds (Int32.Parse prevWord) + | 'g' -> greens <- max greens (Int32.Parse prevWord) + | _ -> () + + prevWord <- words.Current + + answer <- answer + (reds * greens * blues) + + answer diff --git a/AdventOfCode2023.FSharp/Test/Test.fsproj b/AdventOfCode2023.FSharp/Test/Test.fsproj index c095584..4c64424 100644 --- a/AdventOfCode2023.FSharp/Test/Test.fsproj +++ b/AdventOfCode2023.FSharp/Test/Test.fsproj @@ -9,6 +9,7 @@ + diff --git a/AdventOfCode2023.FSharp/Test/TestDay2.fs b/AdventOfCode2023.FSharp/Test/TestDay2.fs new file mode 100644 index 0000000..e484cd3 --- /dev/null +++ b/AdventOfCode2023.FSharp/Test/TestDay2.fs @@ -0,0 +1,46 @@ +namespace AdventOfCode2023.Test + +open AdventOfCode2023 +open NUnit.Framework +open FsUnitTyped +open System.IO + +[] +module TestDay2 = + + let sample = + """Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green +Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue +Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red +Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red +Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green +""" + + [] + let part1Sample () = sample |> Day2.part1 |> shouldEqual 8 + + [] + let part2Sample () = + sample |> Day2.part2 |> shouldEqual 2286 + + [] + let part1Actual () = + let s = + try + File.ReadAllText (Path.Combine (__SOURCE_DIRECTORY__, "../../inputs/day2.txt")) + with :? FileNotFoundException -> + Assert.Inconclusive () + failwith "unreachable" + + Day2.part1 s |> shouldEqual 2727 + + [] + let part2Actual () = + let s = + try + File.ReadAllText (Path.Combine (__SOURCE_DIRECTORY__, "../../inputs/day2.txt")) + with :? FileNotFoundException -> + Assert.Inconclusive () + failwith "unreachable" + + Day2.part2 s |> shouldEqual 56580