This commit is contained in:
Patrick Stevens
2022-12-09 05:54:44 +00:00
committed by GitHub
parent 1c3a31de26
commit db84b8496b
7 changed files with 2162 additions and 2 deletions

View File

@@ -15,6 +15,7 @@
<EmbeddedResource Include="..\AdventOfCode2022.Test\Inputs\Day6.txt" />
<EmbeddedResource Include="..\AdventOfCode2022.Test\Inputs\Day7.txt" />
<EmbeddedResource Include="..\AdventOfCode2022.Test\Inputs\Day8.txt" />
<EmbeddedResource Include="..\AdventOfCode2022.Test\Inputs\Day9.txt" />
</ItemGroup>
<ItemGroup>

View File

@@ -13,14 +13,14 @@ module Program =
let readResource (name : string) : string =
let asm = Assembly.GetAssembly typeof<Dummy>
use stream = asm.GetManifestResourceStream (sprintf "AdventOfCode2022.App.%s" name)
use stream = asm.GetManifestResourceStream $"AdventOfCode2022.App.%s{name}"
use reader = new StreamReader (stream)
reader.ReadToEnd ()
[<EntryPoint>]
let main _ =
let days = Array.init 8 (fun day -> readResource $"Day%i{day + 1}.txt")
let days = Array.init 9 (fun day -> readResource $"Day%i{day + 1}.txt")
let inline day (i : int) = days.[i - 1]
@@ -68,6 +68,11 @@ module Program =
printfn "%i" (Day8.part1 day8)
printfn "%i" (Day8.part2 day8)
do
let day9 = StringSplitEnumerator.make '\n' (day 9)
printfn "%i" (Day9.part1 day9)
printfn "%i" (Day9.part2 day9)
time.Stop ()
printfn $"Took %i{time.ElapsedMilliseconds}ms"
0

View File

@@ -16,6 +16,7 @@
<Compile Include="Day6.fs" />
<Compile Include="Day7.fs" />
<Compile Include="Day8.fs" />
<Compile Include="Day9.fs" />
<EmbeddedResource Include="Inputs\Day1.txt" />
<EmbeddedResource Include="Inputs\Day2.txt" />
<EmbeddedResource Include="Inputs\Day3.txt" />
@@ -24,6 +25,7 @@
<EmbeddedResource Include="Inputs\Day6.txt" />
<EmbeddedResource Include="Inputs\Day7.txt" />
<EmbeddedResource Include="Inputs\Day8.txt" />
<EmbeddedResource Include="Inputs\Day9.txt" />
</ItemGroup>
<ItemGroup>

View File

@@ -0,0 +1,54 @@
namespace AdventOfCode2022.Test
open System
open NUnit.Framework
open FsUnitTyped
open AdventOfCode2022
[<TestFixture>]
module TestDay9 =
let input =
"""R 4
U 4
L 3
D 1
R 4
D 1
L 5
R 2
"""
[<Test>]
let ``Part 1, given`` () =
Day9.part1 (StringSplitEnumerator.make '\n' input) |> shouldEqual 13
[<Test>]
let ``Part 1`` () =
let input = Assembly.readResource "Day9.txt"
Day9.part1 (StringSplitEnumerator.make '\n' input) |> shouldEqual 6023
[<Test>]
let ``Part 2, given 1`` () =
Day9.part2 (StringSplitEnumerator.make '\n' input) |> shouldEqual 1
let example2 =
"""R 5
U 8
L 8
D 3
R 17
D 10
L 25
U 20
"""
[<Test>]
let ``Part 2, given 2`` () =
Day9.part2 (StringSplitEnumerator.make '\n' example2) |> shouldEqual 36
[<Test>]
let ``Part 2`` () =
let input = Assembly.readResource "Day9.txt"
Day9.part2 (StringSplitEnumerator.make '\n' input) |> shouldEqual 2533

File diff suppressed because it is too large Load Diff

View File

@@ -17,6 +17,7 @@
<Compile Include="Day6.fs" />
<Compile Include="Day7.fs" />
<Compile Include="Day8.fs" />
<Compile Include="Day9.fs" />
</ItemGroup>
</Project>

97
AdventOfCode2022/Day9.fs Normal file
View File

@@ -0,0 +1,97 @@
namespace AdventOfCode2022
open System.Collections.Generic
open System
type Direction =
| Up
| Down
| Left
| Right
[<RequireQualifiedAccess>]
module Day9 =
let parse (lines : StringSplitEnumerator) : (Direction * int) IReadOnlyList =
use mutable enum = lines
let output = ResizeArray ()
for line in enum do
let line = line.TrimEnd ()
if not (line.IsWhiteSpace ()) then
let dir =
match Char.ToUpperInvariant line.[0] with
| 'U' -> Direction.Up
| 'D' -> Direction.Down
| 'L' -> Direction.Left
| 'R' -> Direction.Right
| _ -> failwith "Unexpected direction"
let distance = Int32.Parse (line.Slice 2)
output.Add (dir, distance)
output :> _
type Position = int * int
let bringTailTogether (head : Position) (tail : Position) : Position =
if abs (fst head - fst tail) <= 1 && abs (snd head - snd tail) <= 1 then
tail
elif fst head = fst tail then
fst head, snd head + (if snd head < snd tail then 1 else -1)
elif snd head = snd tail then
fst head + (if fst head < fst tail then 1 else -1), snd head
else
let fstCoord =
if abs (fst head - fst tail + 1) <= 1 then
fst tail - 1
else
fst tail + 1
let sndCoord =
if abs (snd head - snd tail + 1) <= 1 then
snd tail - 1
else
snd tail + 1
(fstCoord, sndCoord)
let newHead (pos : Position) (direction : Direction) : int * int =
match direction with
| Direction.Up -> fst pos, snd pos + 1
| Direction.Down -> fst pos, snd pos - 1
| Direction.Left -> fst pos - 1, snd pos
| Direction.Right -> fst pos + 1, snd pos
let go (count : int) (directions : (Direction * int) seq) : int =
let knots = Array.create count (0, 0)
let tailVisits = HashSet ()
tailVisits.Add (0, 0) |> ignore
for direction, distance in directions do
for _ in 1..distance do
let newHead = newHead knots.[0] direction
knots.[0] <- newHead
for knot in 1 .. knots.Length - 2 do
knots.[knot] <- bringTailTogether knots.[knot - 1] knots.[knot]
let newTail = bringTailTogether knots.[knots.Length - 2] knots.[knots.Length - 1]
if newTail <> knots.[knots.Length - 1] then
knots.[knots.Length - 1] <- newTail
tailVisits.Add newTail |> ignore
tailVisits.Count
let part1 (lines : StringSplitEnumerator) : int =
let directions = parse lines
go 2 directions
let part2 (lines : StringSplitEnumerator) : int =
let directions = parse lines
go 10 directions