mirror of
https://github.com/Smaug123/AdventOfCode2022
synced 2025-10-05 01:28:39 +00:00
Day 9 (#10)
This commit is contained in:
@@ -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>
|
||||
|
@@ -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
|
||||
|
@@ -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>
|
||||
|
54
AdventOfCode2022.Test/Day9.fs
Normal file
54
AdventOfCode2022.Test/Day9.fs
Normal 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
|
2000
AdventOfCode2022.Test/Inputs/Day9.txt
Normal file
2000
AdventOfCode2022.Test/Inputs/Day9.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
97
AdventOfCode2022/Day9.fs
Normal 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
|
Reference in New Issue
Block a user