Day 9 (#10)
All checks were successful
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/push/all-checks-complete Pipeline was successful

Went with Lagrange interpolation instead because that seemed easier.

Co-authored-by: Smaug123 <patrick+github@patrickstevens.co.uk>
Reviewed-on: #10
This commit is contained in:
2023-12-09 09:46:17 +00:00
parent d94663ae0e
commit 3b98d704d1
12 changed files with 281 additions and 78 deletions

View File

@@ -1,23 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<Compile Include="Arr2D.fs" />
<Compile Include="ResizeArray.fs" />
<Compile Include="EfficientString.fs" />
<Compile Include="Arithmetic.fs" />
<Compile Include="Day1.fs" />
<Compile Include="Day2.fs" />
<Compile Include="Day3.fs" />
<Compile Include="Day4.fs" />
<Compile Include="Day5.fs" />
<Compile Include="Day6.fs" />
<Compile Include="Day7.fs" />
<Compile Include="Day8.fs" />
</ItemGroup>
<ItemGroup>
<Compile Include="Arr2D.fs"/>
<Compile Include="ResizeArray.fs"/>
<Compile Include="EfficientString.fs"/>
<Compile Include="Arithmetic.fs"/>
<Compile Include="Rational.fs"/>
<Compile Include="Day1.fs"/>
<Compile Include="Day2.fs"/>
<Compile Include="Day3.fs"/>
<Compile Include="Day4.fs"/>
<Compile Include="Day5.fs"/>
<Compile Include="Day6.fs"/>
<Compile Include="Day7.fs"/>
<Compile Include="Day8.fs"/>
<Compile Include="Day9.fs"/>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,55 @@
namespace AdventOfCode2023
open System
[<RequireQualifiedAccess>]
module Day9 =
let extrapolate (isStart : bool) (arr : ResizeArray<int64>) =
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

View File

@@ -1,7 +1,6 @@
namespace AdventOfCode2023
open System
open System.Globalization
open System.Runtime.CompilerServices
type EfficientString = System.ReadOnlySpan<char>

View File

@@ -0,0 +1,82 @@
namespace AdventOfCode2023
[<Struct>]
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
}
[<RequireQualifiedAccess>]
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