aboutsummaryrefslogtreecommitdiff
path: root/aoc-2022-dotnet/Day13
diff options
context:
space:
mode:
authorTomasz Chojnacki <tomaszchojnacki2001@gmail.com>2022-12-13 16:38:41 +0100
committerTomasz Chojnacki <tomaszchojnacki2001@gmail.com>2022-12-13 16:38:41 +0100
commit6fc820cd0cb61a4bacda5f5b40c98dda850d75da (patch)
tree7d08b0adbf8c1b60be906cab3ee7b76767b6908e /aoc-2022-dotnet/Day13
parenteb7cdaab9b9c13b3594e0abdbbff6f72f8cb4807 (diff)
downloadgleam_aoc2020-6fc820cd0cb61a4bacda5f5b40c98dda850d75da.tar.gz
gleam_aoc2020-6fc820cd0cb61a4bacda5f5b40c98dda850d75da.zip
Upload days 12 and 13
Diffstat (limited to 'aoc-2022-dotnet/Day13')
-rw-r--r--aoc-2022-dotnet/Day13/Day13.fsproj26
-rw-r--r--aoc-2022-dotnet/Day13/Program.fs73
2 files changed, 99 insertions, 0 deletions
diff --git a/aoc-2022-dotnet/Day13/Day13.fsproj b/aoc-2022-dotnet/Day13/Day13.fsproj
new file mode 100644
index 0000000..358ef88
--- /dev/null
+++ b/aoc-2022-dotnet/Day13/Day13.fsproj
@@ -0,0 +1,26 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>net7.0</TargetFramework>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Content Include="test.txt">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </Content>
+ <Content Include="input.txt">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </Content>
+ <Compile Include="Program.fs" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="FParsec" Version="1.1.1" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\Common\Common.fsproj" />
+ </ItemGroup>
+
+</Project>
diff --git a/aoc-2022-dotnet/Day13/Program.fs b/aoc-2022-dotnet/Day13/Program.fs
new file mode 100644
index 0000000..2ff8b8d
--- /dev/null
+++ b/aoc-2022-dotnet/Day13/Program.fs
@@ -0,0 +1,73 @@
+module Day13
+
+#nowarn "0342"
+
+open System
+open System.IO
+open FParsec
+open Common
+
+[<StructuralEquality; CustomComparison>]
+type Packet =
+ | Integer of int
+ | List of Packet list
+
+ static member dividers =
+ [ Packet.parse "[[2]]"
+ Packet.parse "[[6]]" ]
+
+ interface IComparable with
+ member this.CompareTo other =
+ match other with
+ | :? Packet as p -> (this :> IComparable<_>).CompareTo p
+ | _ -> failwith "Can only compare packets with other packets!"
+
+ interface IComparable<Packet> with
+ member this.CompareTo other =
+ match (this, other) with
+ | Integer l, Integer r -> compare l r
+ | List l, List r -> compare l r
+ | (Integer _ as l), (List _ as r) -> compare (List [ l ]) r
+ | (List _ as l), (Integer _ as r) -> compare l (List [ r ])
+
+ static member parse =
+ let ppacket, ppacketImpl = createParserForwardedToRef ()
+ let pinteger = pint32 |>> Integer
+
+ let plist =
+ between (pchar '[') (pchar ']') (sepBy ppacket (pchar ','))
+ |>> List
+
+ ppacketImpl.Value <- pinteger <|> plist
+
+ Util.parse ppacket
+
+let solution (transform, predicate, reducer) =
+ Seq.filter (not << String.IsNullOrWhiteSpace)
+ >> Seq.map Packet.parse
+ >> transform
+ >> Seq.indexed
+ >> Seq.choose (fun (i, p) ->
+ match predicate p with
+ | true -> Some(i + 1)
+ | false -> None)
+ >> Seq.reduce reducer
+
+let part1 =
+ (Seq.chunkBySize 2
+ >> Seq.map (function
+ | [| l; r |] -> compare l r
+ | _ -> failwith "Invalid packet groupings!"),
+ (>=) 0,
+ (+))
+
+let part2 =
+ (Seq.append Packet.dividers >> Seq.sort, (fun p -> List.contains p Packet.dividers), (*))
+
+let test = File.ReadLines("test.txt")
+assert (solution part1 test = 13)
+assert (solution part2 test = 140)
+
+let input = File.ReadLines("input.txt")
+printfn "%d" <| solution part1 input
+printfn "%d" <| solution part2 input