Format and tests
This commit is contained in:
12
.config/dotnet-tools.json
Normal file
12
.config/dotnet-tools.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"fantomas": {
|
||||
"version": "6.2.3",
|
||||
"commands": [
|
||||
"fantomas"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
41
.editorconfig
Normal file
41
.editorconfig
Normal file
@@ -0,0 +1,41 @@
|
||||
root=true
|
||||
|
||||
[*]
|
||||
charset=utf-8
|
||||
end_of_line=crlf
|
||||
trim_trailing_whitespace=true
|
||||
insert_final_newline=true
|
||||
indent_style=space
|
||||
indent_size=4
|
||||
|
||||
# ReSharper properties
|
||||
resharper_xml_indent_size=2
|
||||
resharper_xml_max_line_length=100
|
||||
resharper_xml_tab_width=2
|
||||
|
||||
[*.{csproj,fsproj,sqlproj,targets,props,ts,tsx,css,json}]
|
||||
indent_style=space
|
||||
indent_size=2
|
||||
|
||||
[*.{fs,fsi}]
|
||||
fsharp_bar_before_discriminated_union_declaration=true
|
||||
fsharp_space_before_uppercase_invocation=true
|
||||
fsharp_space_before_class_constructor=true
|
||||
fsharp_space_before_member=true
|
||||
fsharp_space_before_colon=true
|
||||
fsharp_space_before_semicolon=true
|
||||
fsharp_multiline_bracket_style=aligned
|
||||
fsharp_newline_between_type_definition_and_members=true
|
||||
fsharp_align_function_signature_to_indentation=true
|
||||
fsharp_alternative_long_member_definitions=true
|
||||
fsharp_multi_line_lambda_closing_newline=true
|
||||
fsharp_experimental_keep_indent_in_branch=true
|
||||
fsharp_max_value_binding_width=80
|
||||
fsharp_max_record_width=0
|
||||
max_line_length=120
|
||||
end_of_line=lf
|
||||
|
||||
[*.{appxmanifest,build,dtd,nuspec,xaml,xamlx,xoml,xsd}]
|
||||
indent_style=space
|
||||
indent_size=2
|
||||
tab_width=2
|
@@ -99,4 +99,4 @@ module Arr2D =
|
||||
System.Array.Clear a.Elements
|
||||
#else
|
||||
NativePtr.initBlock a.Elements 0uy (uint32 sizeof<'a> * uint32 a.Length)
|
||||
#endif
|
||||
#endif
|
||||
|
@@ -4,11 +4,9 @@ open System.Collections.Generic
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Day3 =
|
||||
let inline private isSymbol (i : byte) =
|
||||
i > 200uy
|
||||
let inline private isSymbol (i : byte) = i > 200uy
|
||||
|
||||
let inline private isGear (i : byte) =
|
||||
i = 255uy
|
||||
let inline private isGear (i : byte) = i = 255uy
|
||||
|
||||
/// Returns the parsed board as a buffer, the length of the buffer (there may be garbage at the end), and
|
||||
/// the number of lines the resulting 2D array has.
|
||||
@@ -16,6 +14,7 @@ module Day3 =
|
||||
let mutable lineCount = 0
|
||||
let mutable len = 0
|
||||
let resultArr = Array.zeroCreate fileContents.Length
|
||||
|
||||
for b in fileContents do
|
||||
if b = byte '.' then
|
||||
resultArr.[len] <- 100uy
|
||||
@@ -39,36 +38,48 @@ module Day3 =
|
||||
|
||||
let isNearSymbol (row : int) (numStart : int) (curCol : int) : bool =
|
||||
let mutable isNearSymbol = false
|
||||
|
||||
if row > 0 then
|
||||
for col = max (numStart - 1) 0 to min curCol (lineLength - 1) do
|
||||
if isSymbol (Arr2D.get contents col (row - 1)) then
|
||||
isNearSymbol <- true
|
||||
|
||||
if row < contents.Height - 1 then
|
||||
for col = max (numStart - 1) 0 to min curCol (lineLength - 1) do
|
||||
if isSymbol (Arr2D.get contents col (row + 1)) then
|
||||
isNearSymbol <- true
|
||||
if (numStart > 0 && isSymbol (Arr2D.get contents (numStart - 1) row)) || (curCol < lineLength && isSymbol (Arr2D.get contents curCol row)) then
|
||||
|
||||
if
|
||||
(numStart > 0 && isSymbol (Arr2D.get contents (numStart - 1) row))
|
||||
|| (curCol < lineLength && isSymbol (Arr2D.get contents curCol row))
|
||||
then
|
||||
isNearSymbol <- true
|
||||
|
||||
isNearSymbol
|
||||
|
||||
let mutable total = 0
|
||||
|
||||
for row = 0 to contents.Height - 1 do
|
||||
let mutable currNum = 0
|
||||
let mutable numStart = -1
|
||||
|
||||
for col = 0 to lineLength - 1 do
|
||||
if Arr2D.get contents col row < 10uy then
|
||||
if numStart = -1 then
|
||||
numStart <- col
|
||||
|
||||
currNum <- currNum * 10 + int (Arr2D.get contents col row)
|
||||
elif numStart > -1 then
|
||||
if isNearSymbol row numStart col then
|
||||
total <- total + currNum
|
||||
|
||||
currNum <- 0
|
||||
numStart <- -1
|
||||
|
||||
if numStart >= 0 then
|
||||
if isNearSymbol row numStart lineLength then
|
||||
total <- total + currNum
|
||||
|
||||
currNum <- 0
|
||||
numStart <- -1
|
||||
|
||||
@@ -79,55 +90,64 @@ module Day3 =
|
||||
|
||||
let isNearGear (row : int) (numStart : int) (curCol : int) : (int * int) IReadOnlyList =
|
||||
let gearsNear = ResizeArray ()
|
||||
|
||||
if row > 0 then
|
||||
for col = max (numStart - 1) 0 to min curCol (lineLength - 1) do
|
||||
if isGear (Arr2D.get contents col (row - 1)) then
|
||||
gearsNear.Add (row - 1, col)
|
||||
|
||||
if row < lineLength - 1 then
|
||||
for col = max (numStart - 1) 0 to min curCol (lineLength - 1) do
|
||||
if isGear (Arr2D.get contents col (row + 1)) then
|
||||
gearsNear.Add (row + 1, col)
|
||||
|
||||
if (numStart > 0 && isGear (Arr2D.get contents (numStart - 1) row)) then
|
||||
gearsNear.Add (row, numStart - 1)
|
||||
|
||||
if (curCol < lineLength && isGear (Arr2D.get contents curCol row)) then
|
||||
gearsNear.Add (row, curCol)
|
||||
|
||||
gearsNear
|
||||
|
||||
let gears = Dictionary<int * int, ResizeArray<int>> ()
|
||||
|
||||
let addGear (gearPos : int * int) (num : int) =
|
||||
match gears.TryGetValue gearPos with
|
||||
| false, _ ->
|
||||
let arr = ResizeArray ()
|
||||
arr.Add num
|
||||
gears.Add (gearPos, arr)
|
||||
| true, arr when arr.Count < 3 ->
|
||||
arr.Add num
|
||||
| true, arr when arr.Count < 3 -> arr.Add num
|
||||
| _ -> ()
|
||||
|
||||
for row = 0 to contents.Height - 1 do
|
||||
let mutable currNum = 0
|
||||
let mutable numStart = -1
|
||||
|
||||
for col = 0 to lineLength - 1 do
|
||||
if Arr2D.get contents col row < 10uy then
|
||||
if numStart = -1 then
|
||||
numStart <- col
|
||||
|
||||
currNum <- currNum * 10 + int (Arr2D.get contents col row)
|
||||
elif numStart > -1 then
|
||||
for gearPos in isNearGear row numStart col do
|
||||
addGear gearPos currNum
|
||||
|
||||
currNum <- 0
|
||||
numStart <- -1
|
||||
|
||||
if numStart >= 0 then
|
||||
for gearPos in isNearGear row numStart lineLength do
|
||||
addGear gearPos currNum
|
||||
|
||||
currNum <- 0
|
||||
numStart <- -1
|
||||
|
||||
let mutable answer = 0
|
||||
for KeyValue(_gearPos, gears) in gears do
|
||||
|
||||
for KeyValue (_gearPos, gears) in gears do
|
||||
if gears.Count = 2 then
|
||||
answer <- answer + gears.[0] * gears.[1]
|
||||
|
||||
answer
|
||||
|
||||
|
@@ -38,6 +38,7 @@ module Program =
|
||||
}
|
||||
#else
|
||||
use ptr = fixed resultArr
|
||||
|
||||
let contents =
|
||||
{
|
||||
Elements = ptr
|
||||
@@ -62,4 +63,4 @@ module Program =
|
||||
endToEnd.Stop ()
|
||||
System.Console.Error.WriteLine ("Total (us): " + (toUs endToEnd.ElapsedTicks).ToString ())
|
||||
|
||||
0
|
||||
0
|
||||
|
@@ -5,7 +5,6 @@
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<RootNamespace>TestProject1</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -13,11 +12,15 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FsUnit" Version="5.6.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/>
|
||||
<PackageReference Include="NUnit" Version="3.13.3"/>
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1"/>
|
||||
<PackageReference Include="NUnit.Analyzers" Version="3.6.1"/>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AdventOfCode2023.FSharp.Lib\AdventOfCode2023.FSharp.Lib.fsproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@@ -1,18 +1,133 @@
|
||||
namespace Test
|
||||
namespace AdventOfCode2023.Test
|
||||
|
||||
#if DEBUG
|
||||
#else
|
||||
#nowarn "9"
|
||||
#endif
|
||||
|
||||
open AdventOfCode2023
|
||||
open NUnit.Framework
|
||||
open FsUnitTyped
|
||||
open System.IO
|
||||
|
||||
[<TestFixture>]
|
||||
module TestDay3 =
|
||||
|
||||
[<Test>]
|
||||
let day1Sample () =
|
||||
()
|
||||
let sample =
|
||||
"""467..114..
|
||||
...*......
|
||||
..35..633.
|
||||
......#...
|
||||
617*......
|
||||
.....+.58.
|
||||
..592.....
|
||||
......755.
|
||||
...$.*....
|
||||
.664.598..
|
||||
"""
|
||||
|
||||
[<Test>]
|
||||
let day1Actual () =
|
||||
540131
|
||||
let part1Sample () =
|
||||
let arr, len, rows = sample.ToCharArray () |> Array.map byte |> Day3.parse
|
||||
|
||||
#if DEBUG
|
||||
let arr =
|
||||
{
|
||||
Elements = arr
|
||||
Width = len / rows
|
||||
}
|
||||
#else
|
||||
use arr = fixed arr
|
||||
|
||||
let arr =
|
||||
{
|
||||
Elements = arr
|
||||
Length = len
|
||||
Width = len / rows
|
||||
}
|
||||
#endif
|
||||
|
||||
arr |> Day3.part1 |> shouldEqual 4361
|
||||
|
||||
[<Test>]
|
||||
let day2Actual () =
|
||||
86879020
|
||||
let part2Sample () =
|
||||
let arr, len, rows = sample.ToCharArray () |> Array.map byte |> Day3.parse
|
||||
|
||||
#if DEBUG
|
||||
let arr =
|
||||
{
|
||||
Elements = arr
|
||||
Width = len / rows
|
||||
}
|
||||
#else
|
||||
use arr = fixed arr
|
||||
|
||||
let arr =
|
||||
{
|
||||
Elements = arr
|
||||
Length = len
|
||||
Width = len / rows
|
||||
}
|
||||
#endif
|
||||
|
||||
arr |> Day3.part2 |> shouldEqual 467835
|
||||
|
||||
[<Test>]
|
||||
let part1Actual () =
|
||||
let bytes =
|
||||
try
|
||||
File.ReadAllBytes (Path.Combine (__SOURCE_DIRECTORY__, "../../inputs/day3.txt"))
|
||||
with :? FileNotFoundException ->
|
||||
Assert.Inconclusive ()
|
||||
failwith "unreachable"
|
||||
|
||||
let arr, len, rows = Day3.parse bytes
|
||||
|
||||
#if DEBUG
|
||||
let arr =
|
||||
{
|
||||
Elements = arr
|
||||
Width = len / rows
|
||||
}
|
||||
#else
|
||||
use arr = fixed arr
|
||||
|
||||
let arr =
|
||||
{
|
||||
Elements = arr
|
||||
Length = len
|
||||
Width = len / rows
|
||||
}
|
||||
#endif
|
||||
|
||||
Day3.part1 arr |> shouldEqual 540131
|
||||
|
||||
[<Test>]
|
||||
let part2Actual () =
|
||||
let bytes =
|
||||
try
|
||||
File.ReadAllBytes (Path.Combine (__SOURCE_DIRECTORY__, "../../inputs/day3.txt"))
|
||||
with :? FileNotFoundException ->
|
||||
Assert.Inconclusive ()
|
||||
failwith "unreachable"
|
||||
|
||||
let arr, len, rows = Day3.parse bytes
|
||||
|
||||
#if DEBUG
|
||||
let arr =
|
||||
{
|
||||
Elements = arr
|
||||
Width = len / rows
|
||||
}
|
||||
#else
|
||||
use arr = fixed arr
|
||||
|
||||
let arr =
|
||||
{
|
||||
Elements = arr
|
||||
Length = len
|
||||
Width = len / rows
|
||||
}
|
||||
#endif
|
||||
|
||||
Day3.part2 arr |> shouldEqual 86879020
|
||||
|
Reference in New Issue
Block a user