diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/AdventOfCode2023.FSharp.Lib.fsproj b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/AdventOfCode2023.FSharp.Lib.fsproj index 73ba81f..4ae55e8 100644 --- a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/AdventOfCode2023.FSharp.Lib.fsproj +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/AdventOfCode2023.FSharp.Lib.fsproj @@ -1,23 +1,25 @@  - - net8.0 - true - + + net8.0 + true + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day9.fs b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day9.fs new file mode 100644 index 0000000..7f8c487 --- /dev/null +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day9.fs @@ -0,0 +1,55 @@ +namespace AdventOfCode2023 + +open System + +[] +module Day9 = + + let extrapolate (isStart : bool) (arr : ResizeArray) = + let mutable answer = 0L + let pos = if isStart then -1L else int64 arr.Count + + for i = 0 to arr.Count - 1 do + let mutable product = Rational.ofInt arr.[i] + + for j = 0 to arr.Count - 1 do + if j <> i then + product <- product * Rational.make (pos - int64 j) (int64 i - int64 j) + + answer <- answer + Rational.assertIntegral product + + answer + + let part1 (s : string) = + use s = StringSplitEnumerator.make '\n' s + let mutable answer = 0L + let arr = ResizeArray () + + for line in s do + arr.Clear () + use line = StringSplitEnumerator.make' ' ' line + + for number in line do + let number = Int64.Parse number + arr.Add number + + answer <- answer + extrapolate false arr + + answer + + let part2 (s : string) = + use s = StringSplitEnumerator.make '\n' s + let mutable answer = 0L + let arr = ResizeArray () + + for line in s do + arr.Clear () + use line = StringSplitEnumerator.make' ' ' line + + for number in line do + let number = Int64.Parse number + arr.Add number + + answer <- answer + extrapolate true arr + + answer diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/EfficientString.fs b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/EfficientString.fs index fdfc2f4..657adfb 100644 --- a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/EfficientString.fs +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/EfficientString.fs @@ -1,7 +1,6 @@ namespace AdventOfCode2023 open System -open System.Globalization open System.Runtime.CompilerServices type EfficientString = System.ReadOnlySpan diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Rational.fs b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Rational.fs new file mode 100644 index 0000000..cc867e8 --- /dev/null +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Rational.fs @@ -0,0 +1,82 @@ +namespace AdventOfCode2023 + +[] +type Rational<'a + when 'a : (static member (+) : 'a * 'a -> 'a) + and 'a : (static member (*) : 'a * 'a -> 'a) + and 'a : (static member (/) : 'a * 'a -> 'a) + and 'a : (static member (-) : 'a * 'a -> 'a) + and 'a : (static member Zero : 'a) + and 'a : (static member One : 'a) + and 'a : comparison> = + { + Numerator : 'a + Denominator : 'a + } + + static member inline (+) (a : Rational<'a>, b : Rational<'a>) = + let numerator = a.Numerator * b.Denominator + b.Numerator * a.Denominator + let denominator = a.Denominator * b.Denominator + let hcf = (Arithmetic.euclideanAlgorithm numerator denominator).Hcf + + { + Numerator = numerator / hcf + Denominator = denominator / hcf + } + + static member inline (*) (a : Rational<'a>, b : Rational<'a>) = + let numerator = a.Numerator * b.Numerator + let denominator = a.Denominator * b.Denominator + let hcf = (Arithmetic.euclideanAlgorithm numerator denominator).Hcf + + { + Numerator = numerator / hcf + Denominator = denominator / hcf + } + +[] +module Rational = + let inline ofInt< ^a + when 'a : (static member (+) : 'a * 'a -> 'a) + and 'a : (static member (*) : 'a * 'a -> 'a) + and 'a : (static member (/) : 'a * 'a -> 'a) + and 'a : (static member (-) : 'a * 'a -> 'a) + and 'a : (static member Zero : 'a) + and 'a : (static member One : 'a) + and 'a : comparison> + (a : 'a) + = + { + Numerator = a + Denominator = LanguagePrimitives.GenericOne + } + + let inline make< ^a + when 'a : (static member (+) : 'a * 'a -> 'a) + and 'a : (static member (*) : 'a * 'a -> 'a) + and 'a : (static member (/) : 'a * 'a -> 'a) + and 'a : (static member (-) : 'a * 'a -> 'a) + and 'a : (static member Zero : 'a) + and 'a : (static member One : 'a) + and 'a : comparison> + (numerator : 'a) + (denominator : 'a) + = + let hcf = (Arithmetic.euclideanAlgorithm numerator denominator).Hcf + + { + Numerator = numerator / hcf + Denominator = denominator / hcf + } + + let inline assertIntegral< ^a + when 'a : (static member (+) : 'a * 'a -> 'a) + and 'a : (static member (*) : 'a * 'a -> 'a) + and 'a : (static member (/) : 'a * 'a -> 'a) + and 'a : (static member (-) : 'a * 'a -> 'a) + and 'a : (static member Zero : 'a) + and 'a : (static member One : 'a) + and 'a : comparison> + (r : Rational<'a>) + = + r.Numerator diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.fsproj b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.fsproj index c59ca02..745dccd 100644 --- a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.fsproj +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.fsproj @@ -1,28 +1,28 @@  - - Exe - net8.0 - true - true - true + + Exe + net8.0 + true + true + true - Speed - false + Speed + false - false - false - false - false - false - + false + false + false + false + false + - - - + + + - - - + + + diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp/Program.fs b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp/Program.fs index 236c282..f69ac90 100644 --- a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp/Program.fs +++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp/Program.fs @@ -179,6 +179,22 @@ module Program = Console.WriteLine (part2.ToString ()) Console.Error.WriteLine ((1_000.0 * float sw.ElapsedTicks / float Stopwatch.Frequency).ToString () + "ms") + Console.WriteLine "=====Day 9=====" + + do + let input = Path.Combine (dir.FullName, "day9.txt") |> File.ReadAllText + + sw.Restart () + let part1 = Day9.part1 input + sw.Stop () + Console.WriteLine (part1.ToString ()) + Console.Error.WriteLine ((1_000.0 * float sw.ElapsedTicks / float Stopwatch.Frequency).ToString () + "ms") + sw.Restart () + let part2 = Day9.part2 input + sw.Stop () + Console.WriteLine (part2.ToString ()) + Console.Error.WriteLine ((1_000.0 * float sw.ElapsedTicks / float Stopwatch.Frequency).ToString () + "ms") + endToEnd.Stop () Console.Error.WriteLine ( diff --git a/AdventOfCode2023.FSharp/Test/Test.fsproj b/AdventOfCode2023.FSharp/Test/Test.fsproj index 9a4c538..7c324d0 100644 --- a/AdventOfCode2023.FSharp/Test/Test.fsproj +++ b/AdventOfCode2023.FSharp/Test/Test.fsproj @@ -1,44 +1,46 @@ - - net8.0 + + net8.0 - false - true - + false + true + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - - + + + diff --git a/AdventOfCode2023.FSharp/Test/TestDay5.fs b/AdventOfCode2023.FSharp/Test/TestDay5.fs index 2739873..c119d76 100644 --- a/AdventOfCode2023.FSharp/Test/TestDay5.fs +++ b/AdventOfCode2023.FSharp/Test/TestDay5.fs @@ -1,6 +1,5 @@ namespace AdventOfCode2023.Test -open System open AdventOfCode2023 open NUnit.Framework open FsUnitTyped diff --git a/AdventOfCode2023.FSharp/Test/TestDay6.fs b/AdventOfCode2023.FSharp/Test/TestDay6.fs index 6235479..1119907 100644 --- a/AdventOfCode2023.FSharp/Test/TestDay6.fs +++ b/AdventOfCode2023.FSharp/Test/TestDay6.fs @@ -1,6 +1,5 @@ namespace AdventOfCode2023.Test -open System open AdventOfCode2023 open NUnit.Framework open FsUnitTyped diff --git a/AdventOfCode2023.FSharp/Test/TestDay7.fs b/AdventOfCode2023.FSharp/Test/TestDay7.fs index 38f91ee..03983e5 100644 --- a/AdventOfCode2023.FSharp/Test/TestDay7.fs +++ b/AdventOfCode2023.FSharp/Test/TestDay7.fs @@ -1,6 +1,5 @@ namespace AdventOfCode2023.Test -open System open AdventOfCode2023 open NUnit.Framework open FsUnitTyped diff --git a/AdventOfCode2023.FSharp/Test/TestDay9.fs b/AdventOfCode2023.FSharp/Test/TestDay9.fs new file mode 100644 index 0000000..6d9c969 --- /dev/null +++ b/AdventOfCode2023.FSharp/Test/TestDay9.fs @@ -0,0 +1,47 @@ +namespace AdventOfCode2023.Test + +open AdventOfCode2023 +open NUnit.Framework +open FsUnitTyped +open System.IO + +[] +module TestDay9 = + + let sample = Assembly.getEmbeddedResource typeof.Assembly "day9.txt" + + [] + let part1Sample () = + sample |> Day9.part1 |> shouldEqual 114L + + [] + let part2Sample () = + Assembly.getEmbeddedResource typeof.Assembly "day9.txt" + |> Day9.part2 + |> shouldEqual 2L + + [] + let part1Actual () = + let s = + try + File.ReadAllText (Path.Combine (__SOURCE_DIRECTORY__, "../../inputs/day9.txt")) + with + | :? DirectoryNotFoundException + | :? FileNotFoundException -> + Assert.Inconclusive () + failwith "unreachable" + + Day9.part1 s |> shouldEqual 1898776583L + + [] + let part2Actual () = + let s = + try + File.ReadAllText (Path.Combine (__SOURCE_DIRECTORY__, "../../inputs/day9.txt")) + with + | :? DirectoryNotFoundException + | :? FileNotFoundException -> + Assert.Inconclusive () + failwith "unreachable" + + Day9.part2 s |> shouldEqual 1100L diff --git a/AdventOfCode2023.FSharp/Test/samples/day9.txt b/AdventOfCode2023.FSharp/Test/samples/day9.txt new file mode 100644 index 0000000..539a763 --- /dev/null +++ b/AdventOfCode2023.FSharp/Test/samples/day9.txt @@ -0,0 +1,3 @@ +0 3 6 9 12 15 +1 3 6 10 15 21 +10 13 16 21 30 45