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