diff --git a/AdventOfCode2022.App/AdventOfCode2022.App.fsproj b/AdventOfCode2022.App/AdventOfCode2022.App.fsproj
index 71049a2..f48094e 100644
--- a/AdventOfCode2022.App/AdventOfCode2022.App.fsproj
+++ b/AdventOfCode2022.App/AdventOfCode2022.App.fsproj
@@ -15,6 +15,7 @@
+
diff --git a/AdventOfCode2022.App/Program.fs b/AdventOfCode2022.App/Program.fs
index 59c3f17..f0bf87b 100644
--- a/AdventOfCode2022.App/Program.fs
+++ b/AdventOfCode2022.App/Program.fs
@@ -13,14 +13,14 @@ module Program =
let readResource (name : string) : string =
let asm = Assembly.GetAssembly typeof
- use stream = asm.GetManifestResourceStream (sprintf "AdventOfCode2022.App.%s" name)
+ use stream = asm.GetManifestResourceStream $"AdventOfCode2022.App.%s{name}"
use reader = new StreamReader (stream)
reader.ReadToEnd ()
[]
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
diff --git a/AdventOfCode2022.Test/AdventOfCode2022.Test.fsproj b/AdventOfCode2022.Test/AdventOfCode2022.Test.fsproj
index 236aef7..17981d6 100644
--- a/AdventOfCode2022.Test/AdventOfCode2022.Test.fsproj
+++ b/AdventOfCode2022.Test/AdventOfCode2022.Test.fsproj
@@ -16,6 +16,7 @@
+
@@ -24,6 +25,7 @@
+
diff --git a/AdventOfCode2022.Test/Day9.fs b/AdventOfCode2022.Test/Day9.fs
new file mode 100644
index 0000000..eabce95
--- /dev/null
+++ b/AdventOfCode2022.Test/Day9.fs
@@ -0,0 +1,54 @@
+namespace AdventOfCode2022.Test
+
+open System
+open NUnit.Framework
+open FsUnitTyped
+open AdventOfCode2022
+
+[]
+module TestDay9 =
+
+ let input =
+ """R 4
+U 4
+L 3
+D 1
+R 4
+D 1
+L 5
+R 2
+"""
+
+ []
+ let ``Part 1, given`` () =
+ Day9.part1 (StringSplitEnumerator.make '\n' input) |> shouldEqual 13
+
+ []
+ let ``Part 1`` () =
+ let input = Assembly.readResource "Day9.txt"
+
+ Day9.part1 (StringSplitEnumerator.make '\n' input) |> shouldEqual 6023
+
+ []
+ 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
+"""
+
+ []
+ let ``Part 2, given 2`` () =
+ Day9.part2 (StringSplitEnumerator.make '\n' example2) |> shouldEqual 36
+
+ []
+ let ``Part 2`` () =
+ let input = Assembly.readResource "Day9.txt"
+ Day9.part2 (StringSplitEnumerator.make '\n' input) |> shouldEqual 2533
diff --git a/AdventOfCode2022.Test/Inputs/Day9.txt b/AdventOfCode2022.Test/Inputs/Day9.txt
new file mode 100644
index 0000000..9271e2f
--- /dev/null
+++ b/AdventOfCode2022.Test/Inputs/Day9.txt
@@ -0,0 +1,2000 @@
+U 2
+D 2
+R 1
+D 2
+R 2
+D 2
+R 2
+D 1
+L 2
+U 2
+L 2
+R 1
+L 1
+U 1
+L 2
+D 1
+R 2
+D 1
+U 2
+R 2
+D 2
+U 2
+R 2
+L 1
+D 2
+R 2
+U 2
+R 1
+L 1
+U 2
+R 1
+U 2
+L 1
+R 2
+L 1
+R 1
+U 2
+L 2
+R 1
+D 2
+U 1
+R 1
+L 1
+U 2
+D 2
+U 2
+R 1
+D 1
+L 2
+U 1
+R 2
+L 2
+D 1
+U 2
+D 2
+R 2
+D 2
+R 2
+D 1
+R 1
+D 1
+U 2
+L 1
+R 2
+D 2
+L 2
+R 1
+L 2
+R 1
+D 1
+R 2
+D 2
+U 2
+L 2
+U 2
+R 1
+L 1
+D 2
+U 1
+D 2
+L 2
+D 1
+U 2
+R 1
+D 2
+L 2
+U 2
+D 2
+R 2
+L 1
+R 2
+L 1
+U 2
+L 2
+U 2
+R 1
+D 2
+U 1
+D 2
+R 2
+U 2
+D 1
+U 1
+L 1
+R 1
+U 2
+R 2
+D 1
+R 2
+L 1
+U 2
+L 2
+R 1
+D 1
+R 2
+U 3
+R 2
+D 1
+L 1
+U 2
+D 1
+U 2
+D 3
+U 2
+R 3
+L 3
+R 2
+L 1
+U 2
+L 2
+U 2
+D 1
+R 3
+U 2
+L 3
+R 3
+L 3
+D 3
+L 3
+U 3
+D 3
+L 3
+R 3
+D 1
+L 2
+D 1
+L 2
+D 1
+R 3
+L 3
+D 2
+R 3
+D 3
+R 2
+U 3
+R 3
+D 1
+U 2
+R 1
+D 2
+L 3
+U 3
+D 3
+R 2
+L 1
+D 2
+L 3
+R 2
+D 2
+L 3
+D 1
+R 2
+L 1
+R 3
+D 3
+U 3
+L 1
+D 2
+R 2
+U 1
+L 3
+R 1
+D 1
+U 3
+L 2
+D 1
+R 1
+D 2
+R 2
+U 2
+L 3
+U 1
+R 2
+U 3
+L 2
+U 1
+L 3
+R 3
+L 1
+R 1
+L 1
+U 2
+L 2
+D 2
+R 2
+D 1
+R 3
+L 3
+R 2
+D 3
+R 3
+L 3
+D 2
+U 2
+L 3
+U 3
+R 2
+D 1
+R 1
+L 1
+D 1
+U 1
+L 2
+D 3
+U 3
+D 1
+U 2
+D 2
+L 1
+R 2
+U 3
+D 2
+R 4
+D 1
+U 1
+R 3
+D 3
+U 1
+D 3
+U 1
+L 3
+R 4
+L 3
+U 2
+D 1
+L 4
+D 3
+R 3
+D 4
+U 2
+D 3
+L 3
+D 2
+R 2
+U 3
+D 4
+L 4
+D 4
+U 1
+L 3
+U 2
+L 4
+R 2
+L 3
+D 4
+L 4
+D 4
+L 1
+U 1
+D 1
+L 3
+U 2
+L 1
+R 1
+D 3
+R 3
+L 1
+U 2
+L 1
+U 3
+R 2
+L 3
+R 3
+U 1
+L 1
+R 3
+D 2
+U 1
+D 1
+U 1
+L 1
+R 3
+L 2
+U 2
+R 2
+U 3
+R 2
+U 2
+D 3
+R 1
+L 4
+R 2
+L 4
+U 1
+L 2
+R 2
+L 2
+U 4
+R 3
+U 3
+L 2
+U 3
+R 1
+L 4
+D 3
+R 4
+U 2
+L 2
+R 2
+D 2
+R 1
+U 1
+L 4
+R 2
+U 3
+R 2
+U 4
+L 3
+R 4
+D 1
+R 4
+L 2
+U 2
+R 5
+U 2
+D 2
+R 1
+U 1
+R 5
+L 2
+U 3
+D 1
+R 1
+L 3
+R 4
+L 1
+D 5
+R 1
+U 5
+L 4
+U 5
+D 1
+L 4
+R 3
+U 1
+R 1
+L 4
+R 5
+D 4
+R 1
+U 2
+R 5
+L 4
+R 1
+L 5
+D 4
+U 3
+R 1
+U 1
+R 1
+D 4
+U 3
+L 2
+R 1
+D 2
+L 4
+R 4
+L 1
+U 5
+D 3
+R 5
+D 1
+L 5
+R 3
+L 1
+R 2
+U 5
+D 4
+U 5
+L 5
+R 5
+U 5
+L 3
+D 3
+L 5
+U 1
+D 2
+L 2
+R 3
+D 3
+R 2
+U 1
+D 4
+L 4
+D 5
+L 1
+R 1
+U 5
+R 2
+U 2
+L 1
+U 4
+D 5
+R 1
+L 4
+D 1
+L 1
+U 3
+D 1
+R 2
+L 3
+D 4
+R 2
+L 4
+D 5
+U 3
+L 3
+U 4
+R 5
+L 3
+R 1
+U 3
+R 4
+D 4
+R 2
+D 3
+R 2
+U 1
+L 3
+U 1
+D 5
+L 1
+D 3
+L 4
+R 3
+D 6
+R 2
+D 5
+U 3
+L 2
+R 1
+D 6
+R 5
+L 5
+R 5
+L 3
+U 2
+R 1
+U 3
+R 6
+U 5
+D 1
+L 1
+U 3
+L 4
+U 5
+R 1
+L 2
+R 1
+U 2
+D 2
+L 4
+R 3
+D 3
+L 3
+D 6
+U 2
+L 3
+R 5
+U 4
+L 2
+R 2
+L 5
+D 5
+L 4
+D 4
+R 1
+L 5
+U 1
+L 6
+D 3
+R 6
+L 1
+R 6
+U 5
+R 4
+L 5
+D 5
+R 5
+U 6
+D 4
+U 6
+L 4
+U 4
+L 4
+R 1
+U 2
+R 2
+D 2
+L 5
+D 1
+R 5
+U 2
+D 1
+U 3
+D 4
+U 2
+R 6
+L 2
+R 3
+L 2
+D 1
+U 4
+L 1
+D 1
+U 2
+R 3
+L 4
+D 2
+R 6
+L 5
+U 5
+D 2
+L 3
+U 2
+R 3
+U 6
+R 5
+L 4
+R 1
+L 4
+U 5
+R 3
+U 4
+L 2
+U 5
+R 3
+U 3
+R 2
+U 2
+D 5
+U 4
+D 1
+R 6
+D 5
+L 2
+D 6
+U 2
+L 5
+R 7
+L 5
+U 5
+R 4
+U 4
+R 5
+U 7
+L 5
+U 5
+D 1
+U 2
+R 5
+D 4
+U 7
+R 7
+L 2
+U 4
+D 1
+U 4
+D 6
+U 5
+D 4
+L 6
+D 2
+L 5
+U 6
+D 3
+U 1
+R 6
+D 4
+U 7
+L 2
+R 4
+U 1
+D 6
+R 6
+D 7
+R 3
+U 5
+L 5
+U 2
+D 1
+L 1
+D 4
+L 5
+R 4
+U 6
+R 4
+D 2
+R 6
+D 5
+R 5
+L 6
+R 5
+D 6
+U 3
+D 6
+R 7
+D 6
+U 2
+R 4
+U 4
+L 1
+R 1
+L 6
+D 6
+R 6
+D 1
+U 2
+L 5
+D 2
+R 2
+L 1
+U 3
+R 1
+L 5
+D 7
+U 4
+L 5
+D 4
+R 7
+D 2
+L 7
+R 5
+L 2
+R 7
+D 6
+R 6
+U 1
+D 2
+U 3
+R 2
+L 4
+R 4
+D 6
+U 6
+L 3
+R 1
+U 3
+L 4
+D 6
+U 5
+D 2
+R 3
+D 4
+L 5
+D 5
+R 1
+D 2
+L 4
+U 2
+D 1
+L 7
+D 8
+L 8
+R 5
+U 2
+L 3
+R 1
+U 7
+L 8
+R 8
+D 4
+R 7
+U 7
+L 7
+U 1
+L 2
+D 4
+U 6
+R 8
+D 4
+L 5
+R 2
+D 8
+L 5
+D 1
+U 2
+R 5
+U 5
+R 1
+U 7
+D 1
+R 4
+D 8
+R 3
+L 2
+U 1
+L 5
+R 5
+U 6
+L 2
+U 3
+L 8
+U 8
+D 3
+U 4
+R 6
+U 3
+D 3
+L 4
+U 8
+R 7
+U 7
+R 8
+D 7
+L 6
+R 6
+D 7
+U 3
+D 1
+L 1
+U 7
+L 6
+U 3
+D 1
+U 7
+L 8
+R 5
+U 5
+L 6
+R 2
+D 7
+L 6
+D 3
+R 6
+D 5
+R 6
+L 4
+U 1
+L 2
+D 6
+R 5
+U 1
+D 5
+L 6
+D 8
+R 3
+D 7
+R 5
+D 8
+U 6
+D 2
+L 1
+U 4
+D 8
+U 1
+D 6
+L 2
+R 5
+U 3
+L 4
+U 2
+R 6
+U 6
+R 1
+D 8
+L 2
+U 5
+R 9
+D 5
+L 8
+D 5
+R 7
+D 2
+U 1
+R 4
+L 1
+D 9
+R 4
+U 5
+D 2
+U 7
+R 9
+D 9
+L 8
+U 1
+R 3
+L 5
+R 5
+D 4
+R 3
+D 3
+R 2
+U 3
+D 5
+L 8
+R 3
+U 8
+D 9
+U 1
+R 8
+D 6
+U 2
+L 6
+R 7
+L 1
+R 2
+L 4
+U 7
+R 8
+D 3
+R 4
+D 5
+L 4
+R 1
+D 4
+R 8
+U 1
+L 4
+R 8
+L 3
+U 3
+L 3
+U 7
+R 5
+U 5
+R 3
+U 3
+L 5
+R 8
+U 7
+L 9
+U 9
+D 8
+R 7
+L 2
+R 1
+D 9
+L 8
+D 6
+U 7
+R 6
+L 2
+U 7
+L 6
+R 4
+L 7
+R 3
+U 1
+L 2
+U 1
+D 8
+R 9
+D 3
+U 2
+L 5
+R 3
+D 5
+L 8
+U 1
+D 1
+L 6
+U 2
+R 4
+D 4
+R 2
+U 6
+L 4
+R 7
+D 8
+L 3
+D 5
+R 4
+D 7
+R 2
+U 9
+L 4
+R 4
+U 8
+L 9
+R 6
+D 3
+R 8
+D 1
+U 9
+R 7
+U 3
+L 2
+U 10
+D 7
+L 10
+R 7
+D 6
+U 9
+R 4
+D 8
+R 8
+L 4
+U 7
+L 9
+R 7
+U 6
+R 1
+L 1
+D 9
+L 4
+U 8
+L 9
+R 3
+L 1
+D 3
+L 7
+D 2
+U 7
+R 10
+L 7
+D 3
+R 5
+L 9
+D 1
+L 4
+R 1
+D 10
+U 10
+D 1
+L 1
+R 1
+D 8
+U 3
+R 4
+L 5
+U 6
+L 8
+U 9
+L 7
+D 10
+U 7
+L 3
+R 4
+D 7
+L 4
+D 1
+L 8
+R 6
+L 3
+R 5
+L 3
+R 2
+U 4
+L 5
+U 8
+R 9
+U 1
+R 7
+U 5
+L 5
+U 6
+L 4
+D 9
+L 6
+D 8
+U 10
+L 1
+D 8
+R 4
+L 6
+D 6
+U 5
+L 9
+D 6
+U 10
+L 5
+D 5
+R 5
+U 6
+L 4
+R 7
+L 2
+R 5
+L 1
+D 2
+R 3
+U 10
+L 5
+D 6
+U 7
+D 6
+L 4
+R 8
+D 1
+L 6
+U 2
+R 7
+L 3
+U 10
+D 11
+L 1
+D 7
+R 1
+U 8
+D 4
+R 3
+U 6
+D 5
+R 3
+D 9
+L 6
+D 5
+U 4
+R 2
+U 4
+D 9
+U 2
+L 2
+R 2
+D 8
+R 8
+L 3
+D 8
+R 9
+U 1
+D 11
+L 6
+U 3
+L 11
+D 5
+U 6
+D 5
+L 9
+U 11
+L 1
+D 1
+U 7
+D 2
+U 11
+L 10
+U 2
+R 1
+L 4
+D 2
+U 10
+D 2
+R 7
+L 2
+R 10
+U 10
+R 6
+L 7
+U 10
+D 10
+R 8
+U 3
+L 5
+D 10
+L 3
+D 4
+U 5
+L 8
+U 5
+D 10
+L 5
+D 9
+U 7
+L 3
+U 3
+L 6
+U 5
+R 11
+D 1
+U 5
+R 11
+D 5
+U 4
+D 1
+L 4
+D 6
+L 10
+R 8
+D 8
+R 3
+U 4
+D 1
+R 8
+U 9
+D 4
+R 1
+L 6
+D 9
+R 1
+L 2
+R 6
+D 8
+U 3
+R 6
+U 9
+R 2
+L 10
+U 10
+D 2
+L 5
+U 10
+R 4
+U 1
+R 2
+U 6
+D 8
+L 9
+D 5
+L 7
+D 12
+L 10
+R 9
+L 10
+U 3
+L 11
+R 5
+L 5
+D 12
+L 12
+R 11
+U 6
+R 10
+U 12
+L 11
+U 9
+L 12
+R 8
+D 2
+L 2
+U 11
+D 10
+L 9
+U 6
+L 3
+R 1
+D 4
+U 12
+L 6
+R 8
+U 3
+R 6
+L 10
+R 7
+U 4
+R 1
+U 1
+R 2
+L 3
+U 1
+D 1
+R 3
+D 7
+R 12
+D 1
+U 9
+R 2
+D 1
+U 1
+D 1
+L 3
+D 10
+L 8
+D 8
+U 12
+L 10
+R 3
+L 3
+D 2
+U 1
+R 10
+D 11
+U 9
+L 3
+U 5
+L 10
+R 9
+D 9
+L 12
+R 12
+D 9
+R 4
+D 2
+L 12
+U 9
+D 4
+U 9
+R 3
+L 9
+U 6
+L 6
+D 9
+U 6
+R 1
+U 4
+R 1
+L 7
+D 5
+U 7
+L 3
+R 1
+U 9
+R 7
+U 8
+R 3
+L 2
+D 12
+R 11
+D 2
+R 7
+U 7
+L 12
+R 9
+D 8
+U 7
+L 1
+D 1
+R 9
+L 2
+U 13
+R 7
+D 4
+U 3
+D 1
+L 4
+U 7
+L 5
+R 2
+U 8
+L 6
+R 13
+U 7
+D 10
+R 5
+U 5
+D 3
+R 13
+L 5
+R 1
+U 13
+D 3
+R 12
+U 10
+L 3
+R 12
+L 9
+U 7
+D 2
+L 7
+R 11
+D 3
+L 4
+D 11
+R 1
+L 9
+R 5
+D 1
+R 10
+L 2
+R 4
+D 8
+R 10
+D 9
+U 4
+D 5
+L 1
+D 7
+R 12
+D 13
+U 8
+R 4
+D 5
+L 9
+D 8
+U 3
+L 7
+D 8
+L 9
+R 11
+L 13
+R 8
+D 6
+L 13
+R 10
+D 7
+L 10
+R 8
+L 4
+U 6
+L 2
+R 5
+L 13
+U 2
+R 6
+U 8
+L 6
+D 7
+R 2
+U 2
+R 3
+U 9
+L 6
+U 1
+R 8
+D 13
+R 9
+L 10
+U 5
+L 9
+D 10
+R 3
+L 8
+R 1
+L 1
+D 1
+L 3
+R 5
+L 3
+R 10
+L 4
+U 7
+R 8
+D 2
+R 2
+D 2
+U 8
+R 12
+L 9
+D 12
+R 5
+L 4
+R 10
+D 2
+L 1
+D 6
+L 14
+U 13
+R 1
+U 13
+R 3
+U 9
+D 8
+U 13
+L 6
+R 7
+D 13
+U 7
+D 10
+U 1
+R 9
+U 3
+L 12
+R 7
+U 9
+D 13
+U 13
+L 8
+U 12
+D 14
+L 3
+D 5
+L 12
+U 12
+L 12
+D 4
+U 3
+L 2
+R 10
+U 10
+D 4
+L 5
+R 10
+U 13
+D 1
+U 7
+D 11
+U 11
+D 11
+L 7
+R 3
+L 10
+U 10
+R 10
+D 7
+R 9
+U 14
+R 7
+U 4
+R 4
+L 2
+D 9
+R 9
+D 4
+U 10
+D 3
+U 10
+L 5
+R 2
+L 3
+U 8
+R 1
+D 4
+L 6
+D 5
+R 14
+U 2
+D 14
+U 3
+D 2
+R 4
+U 2
+D 11
+U 6
+D 1
+U 13
+D 5
+L 14
+U 10
+L 12
+D 2
+R 12
+D 5
+R 1
+D 2
+U 5
+R 13
+U 2
+R 5
+U 10
+R 8
+U 11
+D 7
+U 13
+L 8
+U 13
+D 15
+L 3
+D 2
+U 9
+R 4
+U 11
+L 5
+R 6
+D 13
+L 13
+D 14
+R 8
+D 1
+L 10
+R 11
+L 7
+D 11
+R 9
+L 15
+D 7
+U 12
+D 7
+L 6
+U 15
+R 9
+U 2
+D 13
+R 5
+D 13
+R 9
+D 14
+R 1
+L 13
+U 7
+L 6
+D 8
+L 6
+D 5
+R 9
+U 12
+R 13
+D 13
+L 3
+U 4
+L 15
+D 7
+R 1
+L 5
+U 11
+D 6
+L 1
+U 12
+D 12
+U 14
+L 15
+R 14
+D 11
+U 9
+D 6
+L 3
+D 10
+R 6
+D 14
+R 10
+L 12
+D 9
+U 3
+D 15
+L 10
+D 1
+L 12
+R 12
+U 2
+D 8
+L 7
+D 4
+L 9
+U 5
+D 8
+L 8
+U 15
+L 1
+U 11
+L 1
+R 7
+L 9
+U 4
+D 8
+R 8
+L 15
+D 3
+R 5
+U 9
+L 14
+R 15
+L 7
+R 1
+L 1
+R 11
+D 13
+U 3
+L 7
+R 3
+L 3
+U 7
+R 7
+D 8
+R 5
+L 9
+R 2
+L 9
+R 11
+U 3
+L 10
+D 2
+L 14
+D 6
+U 10
+D 2
+U 15
+R 9
+L 7
+D 9
+L 14
+D 4
+R 3
+L 5
+D 13
+R 4
+L 10
+R 7
+L 12
+R 3
+D 14
+R 4
+L 13
+U 9
+D 15
+U 9
+D 7
+L 15
+D 1
+U 10
+D 1
+L 7
+R 9
+D 13
+L 11
+R 2
+D 7
+L 12
+R 1
+L 10
+D 7
+L 14
+U 8
+L 15
+R 15
+L 12
+R 14
+D 5
+R 9
+D 4
+L 15
+U 14
+L 12
+R 11
+D 9
+U 12
+L 11
+U 2
+D 10
+L 1
+D 11
+L 9
+R 2
+D 4
+R 7
+U 12
+L 14
+R 9
+L 15
+R 6
+L 1
+D 4
+R 14
+D 10
+L 12
+U 8
+L 15
+U 7
+L 4
+D 3
+L 14
+U 6
+L 6
+R 13
+D 12
+R 14
+D 14
+L 8
+D 3
+R 12
+L 4
+U 16
+R 7
+U 2
+D 12
+R 3
+D 15
+R 14
+D 8
+U 14
+D 7
+U 14
+D 8
+U 8
+R 1
+D 9
+L 5
+U 2
+L 11
+U 5
+L 14
+U 2
+D 7
+R 17
+U 5
+R 9
+D 8
+U 1
+R 1
+U 11
+L 5
+R 10
+U 16
+R 16
+L 5
+R 7
+U 6
+D 12
+L 16
+U 2
+D 4
+L 13
+R 9
+D 12
+R 11
+U 14
+D 16
+R 6
+D 2
+L 6
+D 5
+R 17
+D 17
+R 2
+U 10
+R 7
+L 12
+U 9
+R 5
+D 4
+R 17
+L 10
+U 13
+D 1
+U 3
+D 4
+L 6
+D 6
+L 9
+U 16
+L 6
+D 2
+U 10
+L 7
+D 6
+R 15
+D 15
+L 12
+D 1
+U 6
+R 3
+U 11
+R 8
+U 13
+D 14
+L 13
+R 9
+L 3
+U 4
+D 12
+U 11
+R 15
+L 3
+D 13
+L 5
+R 17
+D 12
+L 16
+U 6
+R 15
+D 6
+R 13
+D 13
+R 8
+D 7
+U 6
+D 11
+R 17
+U 15
+R 15
+L 1
+D 7
+U 12
+R 15
+L 17
+R 6
+U 1
+R 17
+L 5
+U 1
+L 14
+R 14
+L 5
+D 5
+R 2
+L 7
+U 7
+D 8
+L 17
+U 1
+R 16
+U 9
+L 13
+U 12
+R 2
+U 16
+D 8
+U 17
+L 10
+R 5
+U 11
+D 17
+L 15
+R 11
+U 7
+R 9
+L 4
+D 17
+L 2
+R 7
+D 17
+L 7
+U 12
+L 3
+U 13
+D 2
+L 8
+R 3
+D 17
+U 1
+R 17
+L 2
+U 17
+R 10
+U 1
+R 14
+U 8
+L 17
+D 3
+L 13
+D 10
+R 1
+L 11
+U 10
+L 14
+D 15
+R 14
+L 9
+U 1
+R 11
+L 13
+U 12
+L 9
+U 14
+L 12
+U 11
+L 6
+R 4
+D 2
+L 14
+R 13
+U 16
+L 2
+R 11
+D 18
+R 13
+U 3
+D 15
+L 3
+R 12
+U 10
+L 5
+R 3
+L 11
+U 14
+L 15
+R 3
+L 7
+D 5
+U 1
+R 6
+U 14
+D 17
+U 2
+D 15
+U 14
+D 1
+L 7
+D 1
+R 13
+L 9
+U 5
+L 2
+D 14
+U 14
+R 4
+U 14
+R 11
+U 8
+L 9
+D 15
+L 13
+U 17
+L 2
+U 1
+R 11
+U 7
+D 3
+U 8
+L 16
+D 3
+R 11
+L 17
+D 15
+R 16
+U 18
+D 8
+L 4
+U 2
+D 6
+R 15
+D 11
+L 12
+R 9
+D 18
+R 5
+D 1
+R 12
+L 5
+R 6
+L 6
+U 2
+L 15
+R 6
+L 16
+D 17
+U 11
+R 13
+L 10
+D 7
+L 15
+D 19
+R 17
+U 1
+R 19
+L 16
+U 18
+R 5
+L 6
+D 19
+L 1
+R 15
+L 16
+U 17
+D 18
+U 14
+L 19
+R 18
+L 12
+U 10
+D 2
+L 7
+R 1
+U 15
+L 1
+R 14
+U 10
+D 15
+U 4
+L 1
+U 11
+D 12
+U 7
+D 14
+R 14
+D 12
+L 17
+D 3
+R 6
+D 3
+R 4
+L 2
+R 5
+D 3
+L 10
+U 12
+L 12
+R 7
+D 12
+L 10
+R 10
+D 8
+L 13
+R 9
+U 18
+L 14
+R 1
+L 7
+D 18
+L 14
+U 11
+D 8
+R 13
+D 2
+R 10
+L 4
+R 1
+D 7
+U 18
+D 9
+L 5
+D 2
+U 2
+L 11
+R 2
+D 11
+L 13
+D 17
+L 7
+R 9
+L 9
+R 4
+D 7
diff --git a/AdventOfCode2022/AdventOfCode2022.fsproj b/AdventOfCode2022/AdventOfCode2022.fsproj
index 6542bfd..289e020 100644
--- a/AdventOfCode2022/AdventOfCode2022.fsproj
+++ b/AdventOfCode2022/AdventOfCode2022.fsproj
@@ -17,6 +17,7 @@
+
diff --git a/AdventOfCode2022/Day9.fs b/AdventOfCode2022/Day9.fs
new file mode 100644
index 0000000..8cb4165
--- /dev/null
+++ b/AdventOfCode2022/Day9.fs
@@ -0,0 +1,97 @@
+namespace AdventOfCode2022
+
+open System.Collections.Generic
+open System
+
+type Direction =
+ | Up
+ | Down
+ | Left
+ | Right
+
+[]
+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