Compare commits
21 Commits
01d66b8814
...
minimal
Author | SHA1 | Date | |
---|---|---|---|
|
337d11e0e6 | ||
|
a401d8cf5c | ||
|
61f15726a1 | ||
|
d50618676f | ||
|
ad28718b3e | ||
|
8c244330b7 | ||
|
3cd5ae8635 | ||
|
aa2ace9bf9 | ||
|
e64b9f7cf2 | ||
|
4efbddd9d2 | ||
|
56d0b0c44e | ||
|
331092ff44 | ||
9454c0ac1a | |||
|
89958b0fa0 | ||
|
ee38b17138 | ||
|
5c451057bf | ||
|
4a1d9d1cae | ||
|
a48aaa78b1 | ||
|
1f505a7cce | ||
|
a637f79bf1 | ||
|
3a8061e28d |
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
|
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.txt text eol=lf
|
12
.gitignore
vendored
Normal file
12
.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
riderModule.iml
|
||||||
|
_ReSharper.Caches/
|
||||||
|
.idea/
|
||||||
|
*.user
|
||||||
|
*.DotSettings
|
||||||
|
.DS_Store
|
||||||
|
result
|
||||||
|
.profile*
|
||||||
|
|
||||||
|
inputs/
|
10
.woodpecker/.all-checks-complete.yml
Normal file
10
.woodpecker/.all-checks-complete.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
steps:
|
||||||
|
echo:
|
||||||
|
image: alpine
|
||||||
|
commands:
|
||||||
|
- echo "All required checks complete"
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
- build
|
||||||
|
|
||||||
|
skip_clone: true
|
13
.woodpecker/.build.yml
Normal file
13
.woodpecker/.build.yml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
steps:
|
||||||
|
build:
|
||||||
|
image: nixos/nix
|
||||||
|
commands:
|
||||||
|
- echo 'experimental-features = flakes nix-command' >> /etc/nix/nix.conf
|
||||||
|
- nix develop --command dotnet --info
|
||||||
|
- nix develop --command dotnet publish AdventOfCode2023.FSharp/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.fsproj --configuration Release
|
||||||
|
- nix develop --command sh -c "$(find . -type f -name AdventOfCode2023.FSharp | grep Release | grep publish) AdventOfCode2023.FSharp/Test/samples"
|
||||||
|
|
||||||
|
when:
|
||||||
|
- event: "push"
|
||||||
|
evaluate: 'CI_COMMIT_BRANCH == CI_REPO_DEFAULT_BRANCH'
|
||||||
|
- event: "pull_request"
|
@@ -0,0 +1,16 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Arr2D.fs" />
|
||||||
|
<Compile Include="EfficientString.fs" />
|
||||||
|
<Compile Include="Day1.fs" />
|
||||||
|
<Compile Include="Day2.fs" />
|
||||||
|
<Compile Include="Day3.fs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
102
AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Arr2D.fs
Normal file
102
AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Arr2D.fs
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
namespace AdventOfCode2023
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
#else
|
||||||
|
#nowarn "9"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
open Microsoft.FSharp.NativeInterop
|
||||||
|
|
||||||
|
[<Struct>]
|
||||||
|
#if DEBUG
|
||||||
|
type Arr2D<'a> =
|
||||||
|
{
|
||||||
|
Elements : 'a array
|
||||||
|
Width : int
|
||||||
|
}
|
||||||
|
|
||||||
|
member this.Height = this.Elements.Length / this.Width
|
||||||
|
#else
|
||||||
|
type Arr2D<'a when 'a : unmanaged> =
|
||||||
|
{
|
||||||
|
Elements : nativeptr<'a>
|
||||||
|
Length : int
|
||||||
|
Width : int
|
||||||
|
}
|
||||||
|
|
||||||
|
member this.Height = this.Length / this.Width
|
||||||
|
#endif
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module Arr2D =
|
||||||
|
|
||||||
|
/// It's faster to iterate forward over the first argument, `x`.
|
||||||
|
let inline get (arr : Arr2D<'a>) (x : int) (y : int) : 'a =
|
||||||
|
#if DEBUG
|
||||||
|
arr.Elements.[y * arr.Width + x]
|
||||||
|
#else
|
||||||
|
NativePtr.get arr.Elements (y * arr.Width + x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
let inline set (arr : Arr2D<'a>) (x : int) (y : int) (newVal : 'a) : unit =
|
||||||
|
#if DEBUG
|
||||||
|
arr.Elements.[y * arr.Width + x] <- newVal
|
||||||
|
#else
|
||||||
|
NativePtr.write (NativePtr.add arr.Elements (y * arr.Width + x)) newVal
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
let create (width : int) (height : int) (value : 'a) : Arr2D<'a> =
|
||||||
|
let arr = Array.create (width * height) value
|
||||||
|
|
||||||
|
{
|
||||||
|
Width = width
|
||||||
|
Elements = arr
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/// The input array must be at least of size width * height
|
||||||
|
let create (arr : nativeptr<'a>) (width : int) (height : int) (value : 'a) : Arr2D<'a> =
|
||||||
|
{
|
||||||
|
Width = width
|
||||||
|
Elements = arr
|
||||||
|
Length = width * height
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
[<RequiresExplicitTypeArguments>]
|
||||||
|
#if DEBUG
|
||||||
|
let zeroCreate<'a when 'a : unmanaged> (width : int) (height : int) : Arr2D<'a> =
|
||||||
|
{
|
||||||
|
Elements = Array.zeroCreate (width * height)
|
||||||
|
Width = width
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
let zeroCreate<'a when 'a : unmanaged> (elts : nativeptr<'a>) (width : int) (height : int) : Arr2D<'a> =
|
||||||
|
{
|
||||||
|
Elements = elts
|
||||||
|
Width = width
|
||||||
|
Length = width * height
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// The closure is given x and then y.
|
||||||
|
#if DEBUG
|
||||||
|
let inline init (width : int) (height : int) (f : int -> int -> 'a) : Arr2D<'a> =
|
||||||
|
let result = zeroCreate<'a> width height
|
||||||
|
#else
|
||||||
|
let inline init (arr : nativeptr<'a>) (width : int) (height : int) (f : int -> int -> 'a) : Arr2D<'a> =
|
||||||
|
let result = zeroCreate<'a> arr width height
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for y = 0 to height - 1 do
|
||||||
|
for x = 0 to width - 1 do
|
||||||
|
set result x y (f x y)
|
||||||
|
|
||||||
|
result
|
||||||
|
|
||||||
|
let inline clear (a : Arr2D<'a>) : unit =
|
||||||
|
#if DEBUG
|
||||||
|
System.Array.Clear a.Elements
|
||||||
|
#else
|
||||||
|
NativePtr.initBlock a.Elements 0uy (uint32 sizeof<'a> * uint32 a.Length)
|
||||||
|
#endif
|
97
AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day1.fs
Normal file
97
AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day1.fs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
namespace AdventOfCode2023
|
||||||
|
|
||||||
|
open System
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module Day1 =
|
||||||
|
|
||||||
|
let firstDigit (s : ReadOnlySpan<char>) =
|
||||||
|
let mutable pos = 0
|
||||||
|
|
||||||
|
while '0' > s.[pos] || s.[pos] > '9' do
|
||||||
|
pos <- pos + 1
|
||||||
|
|
||||||
|
byte s.[pos] - byte '0'
|
||||||
|
|
||||||
|
// No surrogate pairs please!
|
||||||
|
let lastDigit (s : ReadOnlySpan<char>) =
|
||||||
|
let mutable pos = s.Length - 1
|
||||||
|
|
||||||
|
while '0' > s.[pos] || s.[pos] > '9' do
|
||||||
|
pos <- pos - 1
|
||||||
|
|
||||||
|
byte s.[pos] - byte '0'
|
||||||
|
|
||||||
|
let part1 (s : string) =
|
||||||
|
use enum = StringSplitEnumerator.make '\n' s
|
||||||
|
let mutable total = 0
|
||||||
|
|
||||||
|
for line in enum do
|
||||||
|
if not line.IsEmpty then
|
||||||
|
let firstDigit = firstDigit line
|
||||||
|
let lastDigit = lastDigit line
|
||||||
|
|
||||||
|
total <- total + int (lastDigit + 10uy * firstDigit)
|
||||||
|
|
||||||
|
total
|
||||||
|
|
||||||
|
let table =
|
||||||
|
[|
|
||||||
|
"one", 1uy
|
||||||
|
"two", 2uy
|
||||||
|
"three", 3uy
|
||||||
|
"four", 4uy
|
||||||
|
"five", 5uy
|
||||||
|
"six", 6uy
|
||||||
|
"seven", 7uy
|
||||||
|
"eight", 8uy
|
||||||
|
"nine", 9uy
|
||||||
|
|]
|
||||||
|
|
||||||
|
let firstDigitIncSpelled (s : ReadOnlySpan<char>) =
|
||||||
|
let mutable pos = 0
|
||||||
|
let mutable answer = 255uy
|
||||||
|
|
||||||
|
while answer = 255uy do
|
||||||
|
if s.[pos] >= '0' && s.[pos] <= '9' then
|
||||||
|
answer <- byte s.[pos] - byte '0'
|
||||||
|
else
|
||||||
|
for i, value in table do
|
||||||
|
if
|
||||||
|
pos + i.Length < s.Length
|
||||||
|
&& MemoryExtensions.SequenceEqual (s.Slice (pos, i.Length), i)
|
||||||
|
then
|
||||||
|
answer <- value
|
||||||
|
|
||||||
|
pos <- pos + 1
|
||||||
|
|
||||||
|
answer
|
||||||
|
|
||||||
|
let lastDigitIncSpelled (s : ReadOnlySpan<char>) =
|
||||||
|
let mutable pos = s.Length - 1
|
||||||
|
let mutable answer = 255uy
|
||||||
|
|
||||||
|
while answer = 255uy do
|
||||||
|
if s.[pos] >= '0' && s.[pos] <= '9' then
|
||||||
|
answer <- byte s.[pos] - byte '0'
|
||||||
|
else
|
||||||
|
for i, value in table do
|
||||||
|
if
|
||||||
|
pos - i.Length + 1 >= 0
|
||||||
|
&& MemoryExtensions.SequenceEqual (s.Slice (pos - i.Length + 1, i.Length), i)
|
||||||
|
then
|
||||||
|
answer <- value
|
||||||
|
|
||||||
|
pos <- pos - 1
|
||||||
|
|
||||||
|
answer
|
||||||
|
|
||||||
|
let part2 (s : string) =
|
||||||
|
use enum = StringSplitEnumerator.make '\n' s
|
||||||
|
let mutable total = 0
|
||||||
|
|
||||||
|
for line in enum do
|
||||||
|
if not line.IsEmpty then
|
||||||
|
total <- total + int (10uy * firstDigitIncSpelled line + lastDigitIncSpelled line)
|
||||||
|
|
||||||
|
total
|
61
AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day2.fs
Normal file
61
AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day2.fs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
namespace AdventOfCode2023
|
||||||
|
|
||||||
|
open System
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module Day2 =
|
||||||
|
|
||||||
|
let part1 (s : string) =
|
||||||
|
use lines = StringSplitEnumerator.make '\n' s
|
||||||
|
let mutable answer = 0
|
||||||
|
|
||||||
|
for line in lines do
|
||||||
|
if not line.IsEmpty then
|
||||||
|
use mutable words = StringSplitEnumerator.make' ' ' line
|
||||||
|
let mutable prevWord = ReadOnlySpan<char>.Empty
|
||||||
|
let mutable isOk = true
|
||||||
|
|
||||||
|
while isOk && words.MoveNext () do
|
||||||
|
match words.Current.[0] with
|
||||||
|
| 'b' ->
|
||||||
|
if Int32.Parse prevWord > 14 then
|
||||||
|
isOk <- false
|
||||||
|
| 'r' ->
|
||||||
|
if Int32.Parse prevWord > 12 then
|
||||||
|
isOk <- false
|
||||||
|
| 'g' ->
|
||||||
|
if Int32.Parse prevWord > 13 then
|
||||||
|
isOk <- false
|
||||||
|
| _ -> ()
|
||||||
|
|
||||||
|
prevWord <- words.Current
|
||||||
|
|
||||||
|
if isOk then
|
||||||
|
answer <- answer + Int32.Parse (line.Slice (5, line.IndexOf ':' - 5))
|
||||||
|
|
||||||
|
answer
|
||||||
|
|
||||||
|
let part2 (s : string) =
|
||||||
|
use lines = StringSplitEnumerator.make '\n' s
|
||||||
|
let mutable answer = 0
|
||||||
|
|
||||||
|
for line in lines do
|
||||||
|
if not line.IsEmpty then
|
||||||
|
let mutable reds = 0
|
||||||
|
let mutable blues = 0
|
||||||
|
let mutable greens = 0
|
||||||
|
use mutable words = StringSplitEnumerator.make' ' ' line
|
||||||
|
let mutable prevWord = ReadOnlySpan<char>.Empty
|
||||||
|
|
||||||
|
while words.MoveNext () do
|
||||||
|
match words.Current.[0] with
|
||||||
|
| 'b' -> blues <- max blues (Int32.Parse prevWord)
|
||||||
|
| 'r' -> reds <- max reds (Int32.Parse prevWord)
|
||||||
|
| 'g' -> greens <- max greens (Int32.Parse prevWord)
|
||||||
|
| _ -> ()
|
||||||
|
|
||||||
|
prevWord <- words.Current
|
||||||
|
|
||||||
|
answer <- answer + (reds * greens * blues)
|
||||||
|
|
||||||
|
answer
|
153
AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day3.fs
Normal file
153
AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.Lib/Day3.fs
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
namespace AdventOfCode2023
|
||||||
|
|
||||||
|
open System.Collections.Generic
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module Day3 =
|
||||||
|
let inline private isSymbol (i : byte) = i > 200uy
|
||||||
|
|
||||||
|
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.
|
||||||
|
let parse (fileContents : byte[]) =
|
||||||
|
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
|
||||||
|
len <- len + 1
|
||||||
|
elif b = byte '*' then
|
||||||
|
resultArr.[len] <- 255uy
|
||||||
|
len <- len + 1
|
||||||
|
elif byte '0' <= b && b <= byte '9' then
|
||||||
|
resultArr.[len] <- b - byte '0'
|
||||||
|
len <- len + 1
|
||||||
|
elif b = 10uy then
|
||||||
|
lineCount <- lineCount + 1
|
||||||
|
else
|
||||||
|
resultArr.[len] <- 254uy
|
||||||
|
len <- len + 1
|
||||||
|
|
||||||
|
resultArr, len, lineCount
|
||||||
|
|
||||||
|
let part1 (contents : Arr2D<byte>) =
|
||||||
|
let lineLength = contents.Width
|
||||||
|
|
||||||
|
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
|
||||||
|
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
|
||||||
|
|
||||||
|
total
|
||||||
|
|
||||||
|
let part2 (contents : Arr2D<byte>) =
|
||||||
|
let lineLength = contents.Width
|
||||||
|
|
||||||
|
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
|
||||||
|
| _ -> ()
|
||||||
|
|
||||||
|
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
|
||||||
|
if gears.Count = 2 then
|
||||||
|
answer <- answer + gears.[0] * gears.[1]
|
||||||
|
|
||||||
|
answer
|
@@ -0,0 +1,97 @@
|
|||||||
|
namespace AdventOfCode2023
|
||||||
|
|
||||||
|
open System
|
||||||
|
open System.Globalization
|
||||||
|
open System.Runtime.CompilerServices
|
||||||
|
|
||||||
|
type EfficientString = System.ReadOnlySpan<char>
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module EfficientString =
|
||||||
|
|
||||||
|
let inline isEmpty (s : EfficientString) : bool = s.IsEmpty
|
||||||
|
|
||||||
|
|
||||||
|
let inline ofString (s : string) : EfficientString = s.AsSpan ()
|
||||||
|
|
||||||
|
let inline toString (s : EfficientString) : string = s.ToString ()
|
||||||
|
|
||||||
|
let inline trimStart (s : EfficientString) : EfficientString = s.TrimStart ()
|
||||||
|
|
||||||
|
let inline slice (start : int) (length : int) (s : EfficientString) : EfficientString = s.Slice (start, length)
|
||||||
|
|
||||||
|
let inline equals (a : string) (other : EfficientString) : bool =
|
||||||
|
MemoryExtensions.Equals (other, a.AsSpan (), StringComparison.Ordinal)
|
||||||
|
|
||||||
|
/// Mutates the input to drop up to the first instance of the input char,
|
||||||
|
/// and returns what was dropped.
|
||||||
|
/// If the char is not present, deletes the input.
|
||||||
|
let takeUntil<'a> (c : char) (s : EfficientString byref) : EfficientString =
|
||||||
|
let first = s.IndexOf c
|
||||||
|
|
||||||
|
if first < 0 then
|
||||||
|
let toRet = s
|
||||||
|
s <- EfficientString.Empty
|
||||||
|
toRet
|
||||||
|
else
|
||||||
|
let toRet = slice 0 first s
|
||||||
|
s <- slice (first + 1) (s.Length - first - 1) s
|
||||||
|
toRet
|
||||||
|
|
||||||
|
[<Struct>]
|
||||||
|
[<IsByRefLike>]
|
||||||
|
type StringSplitEnumerator =
|
||||||
|
internal
|
||||||
|
{
|
||||||
|
Original : EfficientString
|
||||||
|
mutable Remaining : EfficientString
|
||||||
|
mutable InternalCurrent : EfficientString
|
||||||
|
SplitOn : char
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IDisposable with
|
||||||
|
member this.Dispose () = ()
|
||||||
|
|
||||||
|
member this.Current : EfficientString = this.InternalCurrent
|
||||||
|
|
||||||
|
member this.MoveNext () =
|
||||||
|
if this.Remaining.Length = 0 then
|
||||||
|
false
|
||||||
|
else
|
||||||
|
this.InternalCurrent <- EfficientString.takeUntil this.SplitOn &this.Remaining
|
||||||
|
true
|
||||||
|
|
||||||
|
member this.GetEnumerator () = this
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module StringSplitEnumerator =
|
||||||
|
|
||||||
|
let make (splitChar : char) (s : string) : StringSplitEnumerator =
|
||||||
|
{
|
||||||
|
Original = EfficientString.ofString s
|
||||||
|
Remaining = EfficientString.ofString s
|
||||||
|
InternalCurrent = EfficientString.Empty
|
||||||
|
SplitOn = splitChar
|
||||||
|
}
|
||||||
|
|
||||||
|
let make' (splitChar : char) (s : ReadOnlySpan<char>) : StringSplitEnumerator =
|
||||||
|
{
|
||||||
|
Original = s
|
||||||
|
Remaining = s
|
||||||
|
InternalCurrent = EfficientString.Empty
|
||||||
|
SplitOn = splitChar
|
||||||
|
}
|
||||||
|
|
||||||
|
let chomp (s : string) (e : byref<StringSplitEnumerator>) : unit =
|
||||||
|
#if DEBUG
|
||||||
|
if not (e.MoveNext ()) || not (EfficientString.equals s e.Current) then
|
||||||
|
failwithf "expected '%s', got '%s'" s (e.Current.ToString ())
|
||||||
|
#else
|
||||||
|
e.MoveNext () |> ignore
|
||||||
|
#endif
|
||||||
|
|
||||||
|
let consumeInt (e : byref<StringSplitEnumerator>) : int =
|
||||||
|
if not (e.MoveNext ()) then
|
||||||
|
failwith "expected an int, got nothing"
|
||||||
|
|
||||||
|
Int32.Parse e.Current
|
28
AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.sln
Normal file
28
AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.sln
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "AdventOfCode2023.FSharp", "AdventOfCode2023.FSharp\AdventOfCode2023.FSharp.fsproj", "{E2EC7715-E2C9-4671-AFBD-84D740B604FE}"
|
||||||
|
EndProject
|
||||||
|
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Test", "Test\Test.fsproj", "{AC9C7858-2F5D-4DE1-8E13-0A87E1EA8598}"
|
||||||
|
EndProject
|
||||||
|
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "AdventOfCode2023.FSharp.Lib", "AdventOfCode2023.FSharp.Lib\AdventOfCode2023.FSharp.Lib.fsproj", "{95CE0568-3D1A-4060-BB54-52460FB1E399}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{E2EC7715-E2C9-4671-AFBD-84D740B604FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E2EC7715-E2C9-4671-AFBD-84D740B604FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E2EC7715-E2C9-4671-AFBD-84D740B604FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E2EC7715-E2C9-4671-AFBD-84D740B604FE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{AC9C7858-2F5D-4DE1-8E13-0A87E1EA8598}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{AC9C7858-2F5D-4DE1-8E13-0A87E1EA8598}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{AC9C7858-2F5D-4DE1-8E13-0A87E1EA8598}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{AC9C7858-2F5D-4DE1-8E13-0A87E1EA8598}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{95CE0568-3D1A-4060-BB54-52460FB1E399}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{95CE0568-3D1A-4060-BB54-52460FB1E399}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{95CE0568-3D1A-4060-BB54-52460FB1E399}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{95CE0568-3D1A-4060-BB54-52460FB1E399}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
@@ -0,0 +1,12 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<PublishAot>true</PublishAot>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Program.fs"/>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
@@ -0,0 +1,7 @@
|
|||||||
|
namespace AdventOfCode2023
|
||||||
|
|
||||||
|
module Program =
|
||||||
|
|
||||||
|
[<EntryPoint>]
|
||||||
|
let main argv =
|
||||||
|
0
|
33
AdventOfCode2023.FSharp/Test/Test.fsproj
Normal file
33
AdventOfCode2023.FSharp/Test/Test.fsproj
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Util.fs" />
|
||||||
|
<Compile Include="TestDay1.fs" />
|
||||||
|
<Compile Include="TestDay2.fs" />
|
||||||
|
<Compile Include="TestDay3.fs" />
|
||||||
|
<EmbeddedResource Include="samples\day1.txt" />
|
||||||
|
<EmbeddedResource Include="samples\day1part1.txt" />
|
||||||
|
<EmbeddedResource Include="samples\day2.txt" />
|
||||||
|
<EmbeddedResource Include="samples\day3.txt" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="FsUnit" Version="5.6.1" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/>
|
||||||
|
<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>
|
47
AdventOfCode2023.FSharp/Test/TestDay1.fs
Normal file
47
AdventOfCode2023.FSharp/Test/TestDay1.fs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
namespace AdventOfCode2023.Test
|
||||||
|
|
||||||
|
open AdventOfCode2023
|
||||||
|
open NUnit.Framework
|
||||||
|
open FsUnitTyped
|
||||||
|
open System.IO
|
||||||
|
|
||||||
|
[<TestFixture>]
|
||||||
|
module TestDay1 =
|
||||||
|
|
||||||
|
let sample1 = Assembly.getEmbeddedResource typeof<Dummy>.Assembly "day1part1.txt"
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let part1Sample () =
|
||||||
|
sample1 |> Day1.part1 |> shouldEqual 142
|
||||||
|
|
||||||
|
let sample2 = Assembly.getEmbeddedResource typeof<Dummy>.Assembly "day1.txt"
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let part2Sample () =
|
||||||
|
sample2 |> Day1.part2 |> shouldEqual 281
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let part1Actual () =
|
||||||
|
let s =
|
||||||
|
try
|
||||||
|
File.ReadAllText (Path.Combine (__SOURCE_DIRECTORY__, "../../inputs/day1.txt"))
|
||||||
|
with
|
||||||
|
| :? DirectoryNotFoundException
|
||||||
|
| :? FileNotFoundException ->
|
||||||
|
Assert.Inconclusive ()
|
||||||
|
failwith "unreachable"
|
||||||
|
|
||||||
|
Day1.part1 s |> shouldEqual 54304
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let part2Actual () =
|
||||||
|
let s =
|
||||||
|
try
|
||||||
|
File.ReadAllText (Path.Combine (__SOURCE_DIRECTORY__, "../../inputs/day1.txt"))
|
||||||
|
with
|
||||||
|
| :? DirectoryNotFoundException
|
||||||
|
| :? FileNotFoundException ->
|
||||||
|
Assert.Inconclusive ()
|
||||||
|
failwith "unreachable"
|
||||||
|
|
||||||
|
Day1.part2 s |> shouldEqual 54418
|
44
AdventOfCode2023.FSharp/Test/TestDay2.fs
Normal file
44
AdventOfCode2023.FSharp/Test/TestDay2.fs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
namespace AdventOfCode2023.Test
|
||||||
|
|
||||||
|
open AdventOfCode2023
|
||||||
|
open NUnit.Framework
|
||||||
|
open FsUnitTyped
|
||||||
|
open System.IO
|
||||||
|
|
||||||
|
[<TestFixture>]
|
||||||
|
module TestDay2 =
|
||||||
|
|
||||||
|
let sample = Assembly.getEmbeddedResource typeof<Dummy>.Assembly "day2.txt"
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let part1Sample () = sample |> Day2.part1 |> shouldEqual 8
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let part2Sample () =
|
||||||
|
sample |> Day2.part2 |> shouldEqual 2286
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let part1Actual () =
|
||||||
|
let s =
|
||||||
|
try
|
||||||
|
File.ReadAllText (Path.Combine (__SOURCE_DIRECTORY__, "../../inputs/day2.txt"))
|
||||||
|
with
|
||||||
|
| :? DirectoryNotFoundException
|
||||||
|
| :? FileNotFoundException ->
|
||||||
|
Assert.Inconclusive ()
|
||||||
|
failwith "unreachable"
|
||||||
|
|
||||||
|
Day2.part1 s |> shouldEqual 2727
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let part2Actual () =
|
||||||
|
let s =
|
||||||
|
try
|
||||||
|
File.ReadAllText (Path.Combine (__SOURCE_DIRECTORY__, "../../inputs/day2.txt"))
|
||||||
|
with
|
||||||
|
| :? DirectoryNotFoundException
|
||||||
|
| :? FileNotFoundException ->
|
||||||
|
Assert.Inconclusive ()
|
||||||
|
failwith "unreachable"
|
||||||
|
|
||||||
|
Day2.part2 s |> shouldEqual 56580
|
126
AdventOfCode2023.FSharp/Test/TestDay3.fs
Normal file
126
AdventOfCode2023.FSharp/Test/TestDay3.fs
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
namespace AdventOfCode2023.Test
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
#else
|
||||||
|
#nowarn "9"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
open AdventOfCode2023
|
||||||
|
open NUnit.Framework
|
||||||
|
open FsUnitTyped
|
||||||
|
open System.IO
|
||||||
|
|
||||||
|
[<TestFixture>]
|
||||||
|
module TestDay3 =
|
||||||
|
|
||||||
|
let sample = Assembly.getEmbeddedResource typeof<Dummy>.Assembly "day3.txt"
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
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 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
|
||||||
|
| :? DirectoryNotFoundException
|
||||||
|
| :? 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
|
||||||
|
| :? DirectoryNotFoundException
|
||||||
|
| :? 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
|
22
AdventOfCode2023.FSharp/Test/Util.fs
Normal file
22
AdventOfCode2023.FSharp/Test/Util.fs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
namespace AdventOfCode2023.Test
|
||||||
|
|
||||||
|
open System.IO
|
||||||
|
open System.Reflection
|
||||||
|
|
||||||
|
type Dummy =
|
||||||
|
class
|
||||||
|
end
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module Assembly =
|
||||||
|
let getEmbeddedResource (assembly : Assembly) (name : string) : string =
|
||||||
|
let names = assembly.GetManifestResourceNames ()
|
||||||
|
let names = names |> Seq.filter (fun s -> s.EndsWith name)
|
||||||
|
|
||||||
|
use s =
|
||||||
|
names
|
||||||
|
|> Seq.exactlyOne
|
||||||
|
|> assembly.GetManifestResourceStream
|
||||||
|
|> fun s -> new StreamReader (s)
|
||||||
|
|
||||||
|
s.ReadToEnd ()
|
7
AdventOfCode2023.FSharp/Test/samples/day1.txt
Normal file
7
AdventOfCode2023.FSharp/Test/samples/day1.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
two1nine
|
||||||
|
eightwothree
|
||||||
|
abcone2threexyz
|
||||||
|
xtwone3four
|
||||||
|
4nineeightseven2
|
||||||
|
zoneight234
|
||||||
|
7pqrstsixteen
|
4
AdventOfCode2023.FSharp/Test/samples/day1part1.txt
Normal file
4
AdventOfCode2023.FSharp/Test/samples/day1part1.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
1abc2
|
||||||
|
pqr3stu8vwx
|
||||||
|
a1b2c3d4e5f
|
||||||
|
treb7uchet
|
5
AdventOfCode2023.FSharp/Test/samples/day2.txt
Normal file
5
AdventOfCode2023.FSharp/Test/samples/day2.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
|
||||||
|
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
|
||||||
|
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
|
||||||
|
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
|
||||||
|
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
|
10
AdventOfCode2023.FSharp/Test/samples/day3.txt
Normal file
10
AdventOfCode2023.FSharp/Test/samples/day3.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
467..114..
|
||||||
|
...*......
|
||||||
|
..35..633.
|
||||||
|
......#...
|
||||||
|
617*......
|
||||||
|
.....+.58.
|
||||||
|
..592.....
|
||||||
|
......755.
|
||||||
|
...$.*....
|
||||||
|
.664.598..
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 Patrick Stevens
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
33
README.md
Normal file
33
README.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# Advent of Code 2023
|
||||||
|
|
||||||
|
[Puzzle site](https://adventofcode.com/2023).
|
||||||
|
|
||||||
|
# Speed
|
||||||
|
|
||||||
|
Ahead-of-time compiled with `PublishAot`, M1 Max.
|
||||||
|
The format is: "answer part1\ntime\nanswer part2\ntime\n...", with possible extra lines indicating how long it took to parse the input if I happen to have split that out.
|
||||||
|
|
||||||
|
After day 3:
|
||||||
|
|
||||||
|
```
|
||||||
|
54304
|
||||||
|
0.549458ms
|
||||||
|
54418
|
||||||
|
0.710375ms
|
||||||
|
2727
|
||||||
|
0.119959ms
|
||||||
|
56580
|
||||||
|
0.155708ms
|
||||||
|
0.1395ms parse
|
||||||
|
540131
|
||||||
|
0.1395ms
|
||||||
|
86879020
|
||||||
|
0.840791ms
|
||||||
|
4.144166ms total
|
||||||
|
```
|
||||||
|
|
||||||
|
# Building yourself
|
||||||
|
|
||||||
|
Note that `PublishAot` assumes a lot of stuff about your environment, which is not necessarily true.
|
||||||
|
The given flake should allow you to complete the publish except for a linking stage at the end: the publish will print out a failed command line, and you'll have to strip out some `-o` flags from it and run it manually.
|
||||||
|
Then run `dotnet publish` again and it should succeed.
|
61
flake.lock
generated
Normal file
61
flake.lock
generated
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1694529238,
|
||||||
|
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1701253981,
|
||||||
|
"narHash": "sha256-ztaDIyZ7HrTAfEEUt9AtTDNoCYxUdSd6NrRHaYOIxtk=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "e92039b55bcd58469325ded85d4f58dd5a4eaf58",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
45
flake.nix
Normal file
45
flake.nix
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
description = "Advent of Code 2023";
|
||||||
|
inputs = {
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = {
|
||||||
|
self,
|
||||||
|
nixpkgs,
|
||||||
|
flake-utils,
|
||||||
|
}:
|
||||||
|
flake-utils.lib.eachDefaultSystem (
|
||||||
|
system: let
|
||||||
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
in
|
||||||
|
# Conditionally include Swift and Apple SDK for Darwin systems
|
||||||
|
let
|
||||||
|
darwinDeps =
|
||||||
|
if system == "x86_64-darwin" || system == "aarch64-darwin"
|
||||||
|
then [
|
||||||
|
pkgs.swift
|
||||||
|
pkgs.darwin.apple_sdk.frameworks.Foundation
|
||||||
|
pkgs.darwin.apple_sdk.frameworks.CryptoKit
|
||||||
|
pkgs.darwin.apple_sdk.frameworks.GSS
|
||||||
|
]
|
||||||
|
else [];
|
||||||
|
in {
|
||||||
|
devShells = {
|
||||||
|
default = pkgs.mkShell {
|
||||||
|
buildInputs = with pkgs;
|
||||||
|
[
|
||||||
|
(with dotnetCorePackages;
|
||||||
|
combinePackages [
|
||||||
|
dotnet-sdk_8
|
||||||
|
dotnetPackages.Nuget
|
||||||
|
])
|
||||||
|
]
|
||||||
|
++ darwinDeps
|
||||||
|
++ [pkgs.zlib pkgs.zlib.dev pkgs.openssl pkgs.icu pkgs.alejandra];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
Reference in New Issue
Block a user