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

Can't be bothered to get it faster

Co-authored-by: Smaug123 <patrick+github@patrickstevens.co.uk>
Reviewed-on: #19
This commit is contained in:
2023-12-23 19:58:35 +00:00
parent f2a2e630d6
commit 7646fb71c3
12 changed files with 715 additions and 1 deletions

View File

@@ -5,10 +5,15 @@
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<EnableStaticNativeInstrumentation>False</EnableStaticNativeInstrumentation>
<EnableDynamicNativeInstrumentation>False</EnableDynamicNativeInstrumentation>
</PropertyGroup>
<ItemGroup>
<Compile Include="Util.fs"/>
<Compile Include="TestIntervalSet.fs" />
<Compile Include="TestList.fs" />
<Compile Include="TestDay1.fs"/>
<Compile Include="TestDay2.fs"/>
<Compile Include="TestDay3.fs"/>
@@ -25,6 +30,7 @@
<Compile Include="TestDay14.fs" />
<Compile Include="TestDay15.fs" />
<Compile Include="TestDay16.fs" />
<Compile Include="TestDay19.fs" />
<EmbeddedResource Include="samples\day1.txt"/>
<EmbeddedResource Include="samples\day1part1.txt"/>
<EmbeddedResource Include="samples\day2.txt"/>
@@ -44,11 +50,14 @@
<EmbeddedResource Include="samples\day14.txt" />
<EmbeddedResource Include="samples\day15.txt" />
<EmbeddedResource Include="samples\day16.txt" />
<EmbeddedResource Include="samples\day19.txt" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FsCheck" Version="2.16.6" />
<PackageReference Include="FsUnit" Version="5.6.1"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
<PackageReference Include="Microsoft.CodeCoverage" Version="17.8.0"/>
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1"/>
<PackageReference Include="NUnit.Analyzers" Version="3.6.1"/>
<PackageReference Include="coverlet.collector" Version="6.0.0"/>

View File

@@ -0,0 +1,55 @@
namespace AdventOfCode2023.Test
open AdventOfCode2023
open NUnit.Framework
open FsUnitTyped
open System.IO
[<TestFixture>]
module TestDay19 =
[<Test>]
let sample = Assembly.getEmbeddedResource typeof<Dummy>.Assembly "day19.txt"
[<Test>]
let part1Sample () =
use mutable s = StringSplitEnumerator.make '\n' sample
let workflows = Day19.readWorkflows &s
Day19.part1 workflows &s |> shouldEqual 19114
[<Test>]
let part2Sample () =
use mutable s = StringSplitEnumerator.make '\n' sample
let workflows = Day19.readWorkflows &s
Day19.part2 workflows &s |> shouldEqual 167409079868000uL
[<Test>]
let part1Actual () =
let s =
try
File.ReadAllText (Path.Combine (__SOURCE_DIRECTORY__, "../../inputs/day19.txt"))
with
| :? DirectoryNotFoundException
| :? FileNotFoundException ->
Assert.Inconclusive ()
failwith "unreachable"
use mutable s = StringSplitEnumerator.make '\n' s
let workflows = Day19.readWorkflows &s
Day19.part1 workflows &s |> shouldEqual 368964
[<Test>]
let part2Actual () =
let s =
try
File.ReadAllText (Path.Combine (__SOURCE_DIRECTORY__, "../../inputs/day19.txt"))
with
| :? DirectoryNotFoundException
| :? FileNotFoundException ->
Assert.Inconclusive ()
failwith "unreachable"
use mutable s = StringSplitEnumerator.make '\n' s
let workflows = Day19.readWorkflows &s
Day19.part2 workflows &s |> shouldEqual 127675188176682uL

View File

@@ -0,0 +1,86 @@
namespace AdventOfCode2023.Test
open System.Threading
open AdventOfCode2023
open NUnit.Framework
open FsUnitTyped
open FsCheck
[<TestFixture>]
module TestIntervalSet =
/// Normalises e.g. (5, 3) to (3, 5) too.
let toIntervalSet (model : (int * int) list) =
(IntervalSet.empty, model)
||> List.fold (fun intervals (x1, x2) -> IntervalSet.add (min x1 x2) (max x1 x2) intervals)
let modelContains (x : int) (model : (int * int) list) =
model
|> List.exists (fun (x1, x2) ->
let x1, x2 = min x1 x2, max x1 x2
x1 <= x && x <= x2
)
[<Test>]
let ``IntervalSet add works`` () =
let property (pos : int ref) (neg : int ref) (x : int) (xs : (int * int) list) =
let intervals = toIntervalSet xs
let actual = IntervalSet.contains x intervals
let expected = modelContains x xs
if actual then
Interlocked.Increment pos |> ignore
else
Interlocked.Increment neg |> ignore
expected = actual
let pos = ref 0
let neg = ref 0
Check.One (
{ Config.Default with
MaxTest = 1000
},
property pos neg
)
printfn "Fraction of positive cases: %f" ((float pos.Value) / (float pos.Value + float neg.Value))
[<Test>]
let ``Intersection works`` () =
let property
(pos : int ref)
(neg : int ref)
(trials : int list)
(xsModel : (int * int) list)
(ysModel : (int * int) list)
=
let xs = toIntervalSet xsModel
let ys = toIntervalSet ysModel
let intervals = IntervalSet.intersection xs ys
for x in trials do
let actual = IntervalSet.contains x intervals
let expected = modelContains x xsModel && modelContains x ysModel
expected |> shouldEqual actual
if actual then
Interlocked.Increment pos |> ignore
else
Interlocked.Increment neg |> ignore
let pos = ref 0
let neg = ref 0
Check.One (
{ Config.Default with
MaxTest = 1000
},
property pos neg
)
printfn "Fraction of positive cases: %f" ((float pos.Value) / (float pos.Value + float neg.Value))

View File

@@ -0,0 +1,20 @@
namespace Test
open NUnit.Framework
open FsUnitTyped
open FsCheck
open AdventOfCode2023
[<TestFixture>]
module TestList =
[<Test>]
let ``n-tuples have the right length`` () =
let property (n : int) (xs : char list) =
let n = min (abs n) 6
let xs = xs |> List.take (min 10 xs.Length)
let tuples = List.nTuples n xs
tuples |> List.forall (fun i -> i.Length = n)
property 1 [ 'v' ] |> shouldEqual true
Check.QuickThrowOnFailure property

View File

@@ -0,0 +1,17 @@
px{a<2006:qkq,m>2090:A,rfg}
pv{a>1716:R,A}
lnx{m>1548:A,A}
rfg{s<537:gd,x>2440:R,A}
qs{s>3448:A,lnx}
qkq{x<1416:A,crn}
crn{x>2662:A,R}
in{s<1351:px,qqz}
qqz{s>2770:qs,m<1801:hdj,R}
gd{a>3333:R,R}
hdj{m>838:A,pv}
{x=787,m=2655,a=1222,s=2876}
{x=1679,m=44,a=2067,s=496}
{x=2036,m=264,a=79,s=2244}
{x=2461,m=1339,a=466,s=291}
{x=2127,m=1623,a=2188,s=1013}