Compare commits
13 Commits
c8c1cdc950
...
minimal
Author | SHA1 | Date | |
---|---|---|---|
|
337d11e0e6 | ||
|
a401d8cf5c | ||
|
61f15726a1 | ||
|
d50618676f | ||
|
ad28718b3e | ||
|
8c244330b7 | ||
|
3cd5ae8635 | ||
|
aa2ace9bf9 | ||
|
e64b9f7cf2 | ||
|
4efbddd9d2 | ||
|
56d0b0c44e | ||
|
331092ff44 | ||
|
89958b0fa0 |
@@ -3,16 +3,9 @@ steps:
|
|||||||
image: nixos/nix
|
image: nixos/nix
|
||||||
commands:
|
commands:
|
||||||
- echo 'experimental-features = flakes nix-command' >> /etc/nix/nix.conf
|
- echo 'experimental-features = flakes nix-command' >> /etc/nix/nix.conf
|
||||||
# Lint
|
- nix develop --command dotnet --info
|
||||||
- "nix flake check"
|
- nix develop --command dotnet publish AdventOfCode2023.FSharp/AdventOfCode2023.FSharp/AdventOfCode2023.FSharp.fsproj --configuration Release
|
||||||
# Test
|
- nix develop --command sh -c "$(find . -type f -name AdventOfCode2023.FSharp | grep Release | grep publish) AdventOfCode2023.FSharp/Test/samples"
|
||||||
- nix develop --command dotnet test AdventOfCode2023.FSharp
|
|
||||||
- nix develop --command dotnet test AdventOfCode2023.FSharp --configuration Release
|
|
||||||
- nix develop --command alejandra --check .
|
|
||||||
- nix develop --command dotnet tool restore
|
|
||||||
- nix develop --command dotnet fantomas --check .
|
|
||||||
# - 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:
|
when:
|
||||||
- event: "push"
|
- event: "push"
|
||||||
|
@@ -11,7 +11,6 @@
|
|||||||
<Compile Include="Day1.fs" />
|
<Compile Include="Day1.fs" />
|
||||||
<Compile Include="Day2.fs" />
|
<Compile Include="Day2.fs" />
|
||||||
<Compile Include="Day3.fs" />
|
<Compile Include="Day3.fs" />
|
||||||
<Compile Include="Day4.fs" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@@ -1,97 +0,0 @@
|
|||||||
namespace AdventOfCode2023
|
|
||||||
|
|
||||||
open System
|
|
||||||
open System.Collections.Generic
|
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
|
||||||
module Day4 =
|
|
||||||
|
|
||||||
let part1 (s : string) =
|
|
||||||
use lines = StringSplitEnumerator.make '\n' s
|
|
||||||
let mutable total = 0
|
|
||||||
let winningNumbers = HashSet ()
|
|
||||||
|
|
||||||
for line in lines do
|
|
||||||
if not (line.IsWhiteSpace ()) then
|
|
||||||
let mutable accumulatingWinning = true
|
|
||||||
winningNumbers.Clear ()
|
|
||||||
use mutable split = StringSplitEnumerator.make' ' ' line
|
|
||||||
StringSplitEnumerator.chomp "Card" &split
|
|
||||||
|
|
||||||
while split.Current.IsEmpty || split.Current.[split.Current.Length - 1] <> ':' do
|
|
||||||
split.MoveNext () |> ignore
|
|
||||||
|
|
||||||
split.MoveNext () |> ignore
|
|
||||||
|
|
||||||
while accumulatingWinning do
|
|
||||||
while split.Current.IsEmpty do
|
|
||||||
split.MoveNext () |> ignore
|
|
||||||
|
|
||||||
if split.Current.[0] = '|' then
|
|
||||||
accumulatingWinning <- false
|
|
||||||
else
|
|
||||||
winningNumbers.Add (Int32.Parse split.Current) |> ignore
|
|
||||||
split.MoveNext () |> ignore
|
|
||||||
|
|
||||||
let mutable answer = 0
|
|
||||||
|
|
||||||
while split.MoveNext () do
|
|
||||||
if not split.Current.IsEmpty then
|
|
||||||
let n = Int32.Parse split.Current
|
|
||||||
|
|
||||||
if winningNumbers.Contains n then
|
|
||||||
answer <- answer + 1
|
|
||||||
|
|
||||||
if answer > 0 then
|
|
||||||
total <- total + (1 <<< (answer - 1))
|
|
||||||
|
|
||||||
total
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let part2 (s : string) =
|
|
||||||
use lines = StringSplitEnumerator.make '\n' s
|
|
||||||
let mutable total = 0
|
|
||||||
let winningNumbers = HashSet ()
|
|
||||||
let winners = ResizeArray ()
|
|
||||||
|
|
||||||
for line in lines do
|
|
||||||
if not (line.IsWhiteSpace ()) then
|
|
||||||
let mutable accumulatingWinning = true
|
|
||||||
winningNumbers.Clear ()
|
|
||||||
use mutable split = StringSplitEnumerator.make' ' ' line
|
|
||||||
StringSplitEnumerator.chomp "Card" &split
|
|
||||||
|
|
||||||
while split.Current.IsEmpty || split.Current.[split.Current.Length - 1] <> ':' do
|
|
||||||
split.MoveNext () |> ignore
|
|
||||||
|
|
||||||
split.MoveNext () |> ignore
|
|
||||||
|
|
||||||
while accumulatingWinning do
|
|
||||||
while split.Current.IsEmpty do
|
|
||||||
split.MoveNext () |> ignore
|
|
||||||
|
|
||||||
if split.Current.[0] = '|' then
|
|
||||||
accumulatingWinning <- false
|
|
||||||
else
|
|
||||||
winningNumbers.Add (Int32.Parse split.Current) |> ignore
|
|
||||||
split.MoveNext () |> ignore
|
|
||||||
|
|
||||||
let mutable answer = 0
|
|
||||||
|
|
||||||
while split.MoveNext () do
|
|
||||||
if not split.Current.IsEmpty then
|
|
||||||
let n = Int32.Parse split.Current
|
|
||||||
|
|
||||||
if winningNumbers.Contains n then
|
|
||||||
answer <- answer + 1
|
|
||||||
|
|
||||||
winners.Add answer
|
|
||||||
|
|
||||||
let ans = Array.create winners.Count 1
|
|
||||||
|
|
||||||
for i = 0 to winners.Count - 1 do
|
|
||||||
for j = i + 1 to winners.[i] + i do
|
|
||||||
ans.[j] <- ans.[j] + ans.[i]
|
|
||||||
|
|
||||||
ans |> Array.sum
|
|
@@ -1,28 +1,12 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<PublishAot>true</PublishAot>
|
<PublishAot>true</PublishAot>
|
||||||
<InvariantGlobalization>true</InvariantGlobalization>
|
|
||||||
<UseSystemResourceKeys>true</UseSystemResourceKeys>
|
|
||||||
|
|
||||||
<IlcOptimizationPreference>Speed</IlcOptimizationPreference>
|
|
||||||
<IlcGenerateStackTraceData>false</IlcGenerateStackTraceData>
|
|
||||||
|
|
||||||
<DebuggerSupport>false</DebuggerSupport>
|
|
||||||
<EnableUnsafeBinaryFormatterSerialization>false</EnableUnsafeBinaryFormatterSerialization>
|
|
||||||
<EventSourceSupport>false</EventSourceSupport>
|
|
||||||
<HttpActivityPropagationSupport>false</HttpActivityPropagationSupport>
|
|
||||||
<MetadataUpdaterSupport>false</MetadataUpdaterSupport>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Program.fs"/>
|
<Compile Include="Program.fs"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\AdventOfCode2023.FSharp.Lib\AdventOfCode2023.FSharp.Lib.fsproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@@ -1,108 +1,7 @@
|
|||||||
namespace AdventOfCode2023
|
namespace AdventOfCode2023
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
#else
|
|
||||||
#nowarn "9"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
open System
|
|
||||||
open System.Diagnostics
|
|
||||||
open System.IO
|
|
||||||
|
|
||||||
module Program =
|
module Program =
|
||||||
|
|
||||||
let inline toUs (ticks : int64) =
|
|
||||||
1_000_000.0 * float ticks / float Stopwatch.Frequency
|
|
||||||
|
|
||||||
[<EntryPoint>]
|
[<EntryPoint>]
|
||||||
let main argv =
|
let main argv =
|
||||||
let endToEnd = Stopwatch.StartNew ()
|
|
||||||
endToEnd.Restart ()
|
|
||||||
|
|
||||||
let dir = DirectoryInfo argv.[0]
|
|
||||||
|
|
||||||
let sw = Stopwatch.StartNew ()
|
|
||||||
|
|
||||||
do
|
|
||||||
sw.Restart ()
|
|
||||||
let input = Path.Combine (dir.FullName, "day1.txt") |> File.ReadAllText
|
|
||||||
let part1 = Day1.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 = Day1.part2 input
|
|
||||||
sw.Stop ()
|
|
||||||
Console.WriteLine (part2.ToString ())
|
|
||||||
Console.Error.WriteLine ((1_000.0 * float sw.ElapsedTicks / float Stopwatch.Frequency).ToString () + "ms")
|
|
||||||
|
|
||||||
do
|
|
||||||
let input = Path.Combine (dir.FullName, "day2.txt") |> File.ReadAllText
|
|
||||||
sw.Restart ()
|
|
||||||
let part1 = Day2.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 = Day2.part2 input
|
|
||||||
sw.Stop ()
|
|
||||||
Console.WriteLine (part2.ToString ())
|
|
||||||
Console.Error.WriteLine ((1_000.0 * float sw.ElapsedTicks / float Stopwatch.Frequency).ToString () + "ms")
|
|
||||||
|
|
||||||
do
|
|
||||||
let input = Path.Combine (dir.FullName, "day3.txt") |> File.ReadAllBytes
|
|
||||||
|
|
||||||
sw.Restart ()
|
|
||||||
let resultArr, len, lineCount = Day3.parse input
|
|
||||||
sw.Stop ()
|
|
||||||
|
|
||||||
Console.Error.WriteLine (
|
|
||||||
(1_000.0 * float sw.ElapsedTicks / float Stopwatch.Frequency).ToString ()
|
|
||||||
+ "ms parse"
|
|
||||||
)
|
|
||||||
#if DEBUG
|
|
||||||
let contents =
|
|
||||||
{
|
|
||||||
Elements = Array.take len resultArr
|
|
||||||
Width = len / lineCount
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
use ptr = fixed resultArr
|
|
||||||
|
|
||||||
let contents =
|
|
||||||
{
|
|
||||||
Elements = ptr
|
|
||||||
Length = len
|
|
||||||
Width = len / lineCount
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
let part1 = Day3.part1 contents
|
|
||||||
sw.Stop ()
|
|
||||||
Console.WriteLine (part1.ToString ())
|
|
||||||
Console.Error.WriteLine ((1_000.0 * float sw.ElapsedTicks / float Stopwatch.Frequency).ToString () + "ms")
|
|
||||||
sw.Restart ()
|
|
||||||
let part2 = Day3.part2 contents
|
|
||||||
Console.WriteLine (part2.ToString ())
|
|
||||||
Console.Error.WriteLine ((1_000.0 * float sw.ElapsedTicks / float Stopwatch.Frequency).ToString () + "ms")
|
|
||||||
|
|
||||||
do
|
|
||||||
let input = Path.Combine (dir.FullName, "day4.txt") |> File.ReadAllText
|
|
||||||
sw.Restart ()
|
|
||||||
let part1 = Day4.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 = Day4.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 (
|
|
||||||
(1_000.0 * float endToEnd.ElapsedTicks / float Stopwatch.Frequency).ToString ()
|
|
||||||
+ "ms total"
|
|
||||||
)
|
|
||||||
|
|
||||||
0
|
0
|
||||||
|
@@ -12,12 +12,10 @@
|
|||||||
<Compile Include="TestDay1.fs" />
|
<Compile Include="TestDay1.fs" />
|
||||||
<Compile Include="TestDay2.fs" />
|
<Compile Include="TestDay2.fs" />
|
||||||
<Compile Include="TestDay3.fs" />
|
<Compile Include="TestDay3.fs" />
|
||||||
<Compile Include="TestDay4.fs" />
|
|
||||||
<EmbeddedResource Include="samples\day1.txt" />
|
<EmbeddedResource Include="samples\day1.txt" />
|
||||||
<EmbeddedResource Include="samples\day1part1.txt" />
|
<EmbeddedResource Include="samples\day1part1.txt" />
|
||||||
<EmbeddedResource Include="samples\day2.txt" />
|
<EmbeddedResource Include="samples\day2.txt" />
|
||||||
<EmbeddedResource Include="samples\day3.txt" />
|
<EmbeddedResource Include="samples\day3.txt" />
|
||||||
<EmbeddedResource Include="samples\day4.txt" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@@ -1,43 +0,0 @@
|
|||||||
namespace AdventOfCode2023.Test
|
|
||||||
|
|
||||||
open AdventOfCode2023
|
|
||||||
open NUnit.Framework
|
|
||||||
open FsUnitTyped
|
|
||||||
open System.IO
|
|
||||||
|
|
||||||
[<TestFixture>]
|
|
||||||
module TestDay4 =
|
|
||||||
|
|
||||||
let sample = Assembly.getEmbeddedResource typeof<Dummy>.Assembly "day4.txt"
|
|
||||||
|
|
||||||
[<Test>]
|
|
||||||
let part1Sample () = sample |> Day4.part1 |> shouldEqual 13
|
|
||||||
|
|
||||||
[<Test>]
|
|
||||||
let part2Sample () = sample |> Day4.part2 |> shouldEqual 30
|
|
||||||
|
|
||||||
[<Test>]
|
|
||||||
let part1Actual () =
|
|
||||||
let s =
|
|
||||||
try
|
|
||||||
File.ReadAllText (Path.Combine (__SOURCE_DIRECTORY__, "../../inputs/day4.txt"))
|
|
||||||
with
|
|
||||||
| :? DirectoryNotFoundException
|
|
||||||
| :? FileNotFoundException ->
|
|
||||||
Assert.Inconclusive ()
|
|
||||||
failwith "unreachable"
|
|
||||||
|
|
||||||
Day4.part1 s |> shouldEqual 27454
|
|
||||||
|
|
||||||
[<Test>]
|
|
||||||
let part2Actual () =
|
|
||||||
let s =
|
|
||||||
try
|
|
||||||
File.ReadAllText (Path.Combine (__SOURCE_DIRECTORY__, "../../inputs/day4.txt"))
|
|
||||||
with
|
|
||||||
| :? DirectoryNotFoundException
|
|
||||||
| :? FileNotFoundException ->
|
|
||||||
Assert.Inconclusive ()
|
|
||||||
failwith "unreachable"
|
|
||||||
|
|
||||||
Day4.part2 s |> shouldEqual 6857330
|
|
@@ -1,6 +0,0 @@
|
|||||||
Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
|
|
||||||
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
|
|
||||||
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
|
|
||||||
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
|
|
||||||
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
|
|
||||||
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
|
|
Reference in New Issue
Block a user