diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/AdventOfCode2023.FSharp.Lib.fsproj b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/AdventOfCode2023.FSharp.Lib.fsproj
index faa1752..0388be6 100644
--- a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/AdventOfCode2023.FSharp.Lib.fsproj
+++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/AdventOfCode2023.FSharp.Lib.fsproj
@@ -23,6 +23,7 @@
+
diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day13.fs b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day13.fs
new file mode 100644
index 0000000..9728f54
--- /dev/null
+++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day13.fs
@@ -0,0 +1,123 @@
+namespace AdventOfCode2023
+
+open System
+
+[]
+module Day13 =
+
+ let rowToInt (row : ReadOnlySpan) : uint32 =
+ let mutable mult = 1ul
+ let mutable answer = 0ul
+
+ for c = row.Length - 1 downto 0 do
+ if row.[c] = '#' then
+ answer <- answer + mult
+
+ mult <- mult * 2ul
+
+ answer
+
+ let colToInt (grid : ReadOnlySpan) (rowLength : int) (colNum : int) =
+ let mutable mult = 1ul
+ let mutable answer = 0ul
+
+ for i = grid.Count '\n' - 1 downto 0 do
+ if grid.[i * (rowLength + 1) + colNum] = '#' then
+ answer <- answer + mult
+
+ mult <- mult * 2ul
+
+ answer
+
+ let verifyHorizontalReflection (group : ResizeArray<'a>) (smaller : int) (bigger : int) : bool =
+ let midPoint = (smaller + bigger) / 2
+
+ let rec isOkWithin (curr : int) =
+ if smaller + curr > midPoint then
+ true
+ else if group.[smaller + curr] = group.[bigger - curr] then
+ isOkWithin (curr + 1)
+ else
+ false
+
+ if not (isOkWithin 0) then
+ false
+ else
+
+ smaller = 0 || bigger = group.Count - 1
+
+ /// Find reflection among rows
+ []
+ let rec findRow (rows : ResizeArray<'a>) (currentLine : int) =
+ if currentLine = rows.Count - 1 then
+ None
+ else
+ let mutable answer = UInt32.MaxValue
+ let mutable i = currentLine
+
+ while i < rows.Count - 1 do
+ i <- i + 1
+
+ if currentLine % 2 <> i % 2 then
+ if rows.[i] = rows.[currentLine] then
+ if verifyHorizontalReflection rows currentLine i then
+ answer <- uint32 (((currentLine + i) / 2) + 1)
+ i <- Int32.MaxValue
+
+ if answer < UInt32.MaxValue then
+ Some answer
+ else
+ findRow rows (currentLine + 1)
+
+ let part1 (s : string) =
+ let mutable s = s.AsSpan ()
+ use lines = StringSplitEnumerator.make' '\n' s
+ let rows = ResizeArray ()
+ let cols = ResizeArray ()
+ let mutable answer = 0ul
+
+ while not s.IsEmpty do
+ rows.Clear ()
+ cols.Clear ()
+ let index = s.IndexOf "\n\n"
+
+ let group =
+ if index < 0 then
+ // last group
+ s
+ else
+ s.Slice (0, index + 1)
+
+ let lineLength = s.IndexOf '\n'
+ cols.EnsureCapacity lineLength |> ignore
+
+ for col = 0 to lineLength - 1 do
+ cols.Add (colToInt group lineLength col)
+
+ for row in StringSplitEnumerator.make' '\n' group do
+ if not row.IsEmpty then
+ rows.Add (rowToInt row)
+
+ match findRow rows 0 with
+ | Some rowIndex -> answer <- answer + 100ul * rowIndex
+ | None ->
+ let colIndex = Option.get (findRow cols 0)
+ answer <- answer + colIndex
+
+ if index < 0 then
+ s <- ReadOnlySpan.Empty
+ else
+ s <- s.Slice (index + 2)
+
+ answer
+
+ let part2 (s : string) =
+ use mutable lines = StringSplitEnumerator.make '\n' s
+
+ let mutable answer = 0uL
+
+ for line in lines do
+ if not line.IsEmpty then
+ ()
+
+ answer
diff --git a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp/Program.fs b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp/Program.fs
index 25640b4..a41eec9 100644
--- a/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp/Program.fs
+++ b/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp/Program.fs
@@ -252,6 +252,22 @@ module Program =
Console.WriteLine (part2.ToString ())
Console.Error.WriteLine ((1_000.0 * float sw.ElapsedTicks / float Stopwatch.Frequency).ToString () + "ms")
+ Console.WriteLine "=====Day 13====="
+
+ do
+ let input = Path.Combine (dir.FullName, "day13.txt") |> File.ReadAllText
+
+ sw.Restart ()
+ let part1 = Day13.part1 input
+ sw.Stop ()
+ Console.WriteLine (part1.ToString ())
+ Console.Error.WriteLine ((1_000.0 * float sw.ElapsedTicks / float Stopwatch.Frequency).ToString () + "ms")
+ sw.Restart ()
+ let part2 = Day13.part2 input
+ sw.Stop ()
+ Console.WriteLine (part2.ToString ())
+ Console.Error.WriteLine ((1_000.0 * float sw.ElapsedTicks / float Stopwatch.Frequency).ToString () + "ms")
+
endToEnd.Stop ()
Console.Error.WriteLine (
diff --git a/AdventOfCode2023.FSharp/Test/Test.fsproj b/AdventOfCode2023.FSharp/Test/Test.fsproj
index 5af2d07..18f4264 100644
--- a/AdventOfCode2023.FSharp/Test/Test.fsproj
+++ b/AdventOfCode2023.FSharp/Test/Test.fsproj
@@ -21,6 +21,7 @@
+
@@ -36,6 +37,7 @@
+
diff --git a/AdventOfCode2023.FSharp/Test/TestDay13.fs b/AdventOfCode2023.FSharp/Test/TestDay13.fs
new file mode 100644
index 0000000..1a6fb47
--- /dev/null
+++ b/AdventOfCode2023.FSharp/Test/TestDay13.fs
@@ -0,0 +1,68 @@
+namespace AdventOfCode2023.Test
+
+open System
+
+open AdventOfCode2023
+open NUnit.Framework
+open FsUnitTyped
+open System.IO
+
+[]
+module TestDay13 =
+
+ []
+ let ``rowToInt test`` () =
+ Day13.rowToInt ("#.##..##.".AsSpan ()) |> shouldEqual 358ul
+
+ []
+ let ``colToInt test`` () =
+ let s =
+ """#.##..##.
+..#.##.#.
+##......#
+##......#
+..#.##.#.
+..##..##.
+#.#.##.#.
+"""
+
+ Day13.colToInt (s.AsSpan ()) 9 0
+ |> shouldEqual (List.sum [ 1 ; 8 ; 16 ; 64 ] |> uint32)
+
+ []
+
+ let sample = Assembly.getEmbeddedResource typeof.Assembly "day13.txt"
+
+ []
+ let part1Sample () =
+ sample |> Day13.part1 |> shouldEqual 405ul
+
+ []
+ let part2Sample () =
+ sample |> Day13.part2 |> shouldEqual 525152uL
+
+ []
+ let part1Actual () =
+ let s =
+ try
+ File.ReadAllText (Path.Combine (__SOURCE_DIRECTORY__, "../../inputs/day13.txt"))
+ with
+ | :? DirectoryNotFoundException
+ | :? FileNotFoundException ->
+ Assert.Inconclusive ()
+ failwith "unreachable"
+
+ Day13.part1 s |> shouldEqual 30158ul
+
+ []
+ let part2Actual () =
+ let s =
+ try
+ File.ReadAllText (Path.Combine (__SOURCE_DIRECTORY__, "../../inputs/day13.txt"))
+ with
+ | :? DirectoryNotFoundException
+ | :? FileNotFoundException ->
+ Assert.Inconclusive ()
+ failwith "unreachable"
+
+ Day13.part2 s |> shouldEqual 3384337640277uL
diff --git a/AdventOfCode2023.FSharp/Test/samples/day13.txt b/AdventOfCode2023.FSharp/Test/samples/day13.txt
new file mode 100644
index 0000000..3b6b5cc
--- /dev/null
+++ b/AdventOfCode2023.FSharp/Test/samples/day13.txt
@@ -0,0 +1,15 @@
+#.##..##.
+..#.##.#.
+##......#
+##......#
+..#.##.#.
+..##..##.
+#.#.##.#.
+
+#...##..#
+#....#..#
+..##..###
+#####.##.
+#####.##.
+..##..###
+#....#..#