Day 8 part 2
Some checks failed
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/push/all-checks-complete Pipeline was successful
ci/woodpecker/pr/build Pipeline failed
ci/woodpecker/pr/all-checks-complete unknown status

This commit is contained in:
Smaug123
2023-12-08 08:40:59 +00:00
parent a9afb23c79
commit 54eb8b20e9
8 changed files with 148 additions and 21 deletions

View File

@@ -9,6 +9,7 @@
<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" />

View File

@@ -0,0 +1,67 @@
namespace AdventOfCode2023
[<RequireQualifiedAccess>]
module Arithmetic =
/// Compute floor(sqrt(i)).
let inline sqrt (i : ^a) =
if i <= LanguagePrimitives.GenericOne then
i
else
let rec go start =
let next = start + LanguagePrimitives.GenericOne
let sqr = next * next
if sqr < LanguagePrimitives.GenericZero then
// Overflow attempted, so the sqrt is between start and next
start
elif i < sqr then
start
elif i = sqr then
next
else
go next
go LanguagePrimitives.GenericOne
/// Find Hcf, A, B s.t. A * a + B * b = Hcf, and Hcf is the highest common factor of a and b.
let inline euclideanAlgorithm
(a : ^a)
(b : ^a)
: {|
Hcf : ^a
A : ^a
B : ^a
|}
=
let rec go rMin1 r sMin1 s tMin1 t =
if r = LanguagePrimitives.GenericZero then
{|
Hcf = rMin1
A = sMin1
B = tMin1
|}
else
let newQ = rMin1 / r
go r (rMin1 - newQ * r) s (sMin1 - newQ * s) t (tMin1 - newQ * t)
let maxA = max a b
let minB = min a b
let result =
go
maxA
minB
LanguagePrimitives.GenericOne
LanguagePrimitives.GenericZero
LanguagePrimitives.GenericZero
LanguagePrimitives.GenericOne
if a = maxA then
result
else
{|
Hcf = result.Hcf
A = result.B
B = result.A
|}

View File

@@ -2,7 +2,6 @@ namespace AdventOfCode2023
open System
open System.Collections.Generic
open System.Globalization
[<RequireQualifiedAccess>]
module Day8 =
@@ -20,8 +19,9 @@ module Day8 =
lines.MoveNext () |> ignore
let stepsLine = lines.Current.TrimEnd()
let stepsLine = lines.Current.TrimEnd ()
let steps = Array.zeroCreate stepsLine.Length
for i = 0 to stepsLine.Length - 1 do
steps.[i] <- (stepsLine.[i] = 'R')
@@ -49,19 +49,60 @@ module Day8 =
let mutable i = 0
let mutable currentNode = "AAA"
let mutable answer = 0
while currentNode <> "ZZZ" do
let instruction = data.Nodes.[currentNode]
if data.Steps.[i] then
// "true" is R
currentNode <- snd instruction
else
currentNode <- fst instruction
i <- (i + 1) % data.Steps.Length
answer <- answer + 1
answer
let inline lcm (periods : ^T[]) =
let mutable lcm = periods.[0]
let mutable i = 1
while i < periods.Length do
let euclid = Arithmetic.euclideanAlgorithm lcm periods.[i]
lcm <- (lcm * periods.[i]) / euclid.Hcf
i <- i + 1
lcm
let part2 (s : string) =
let data = parse s
let mutable answer = 0
answer
let startingNodes =
data.Nodes.Keys
|> Seq.choose (fun k -> if k.[k.Length - 1] = 'A' then Some k else None)
|> Seq.toArray
let periods =
startingNodes
|> Array.map (fun startNode ->
let mutable i = 0
let mutable currentNode = startNode
let mutable answer = 0ul
while currentNode.[currentNode.Length - 1] <> 'Z' do
let instruction = data.Nodes.[currentNode]
if data.Steps.[i] then
// "true" is R
currentNode <- snd instruction
else
currentNode <- fst instruction
i <- (i + 1) % data.Steps.Length
answer <- answer + 1ul
uint64 answer
)
lcm periods