diff --git a/AdventOfCode.sln b/AdventOfCode.sln
index 834a717..6c7413b 100644
--- a/AdventOfCode.sln
+++ b/AdventOfCode.sln
@@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34309.116
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AdventOfCode", "AdventOfCode\AdventOfCode.csproj", "{B4A4D1C2-B2FD-4A90-9A3C-7F8D3DC1D212}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AdventOfCode", "src\AdventOfCode\AdventOfCode.csproj", "{B4A4D1C2-B2FD-4A90-9A3C-7F8D3DC1D212}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdventOfCode.Tests", "tests\AdventOfCode.Tests\AdventOfCode.Tests.csproj", "{6AC23A70-AF1E-4F60-86F1-39A4F1310E6E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -15,6 +17,10 @@ Global
{B4A4D1C2-B2FD-4A90-9A3C-7F8D3DC1D212}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B4A4D1C2-B2FD-4A90-9A3C-7F8D3DC1D212}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B4A4D1C2-B2FD-4A90-9A3C-7F8D3DC1D212}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6AC23A70-AF1E-4F60-86F1-39A4F1310E6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6AC23A70-AF1E-4F60-86F1-39A4F1310E6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6AC23A70-AF1E-4F60-86F1-39A4F1310E6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6AC23A70-AF1E-4F60-86F1-39A4F1310E6E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/README.md b/README.md
index f805220..5e41f3f 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ Solutions to the [Advent of Code](https://adventofcode.com/) puzzles.
| Puzzle | Solution | Date | Notes |
| ------ | -------- | ---- | ----- |
-| [Trebuchet?!](https://adventofcode.com/2023/day/1) | [Solution](./AdventOfCode/Calendar/2023/Day01/Solution.cs) | 2023-01 | Completed |
-| [Cube Conundrum](https://adventofcode.com/2023/day/2) | [Solution](./AdventOfCode/Calendar/2023/Day02/Solution.cs) | 2023-02 | Completed |
-| [Gear Ratios](https://adventofcode.com/2023/day/3) | [Solution](./AdventOfCode/Calendar/2023/Day03/Solution.cs) | 2023-03 | Incomplete |
-| [Scratchcards](https://adventofcode.com/2023/day/4) | [Solution](./AdventOfCode/Calendar/2023/Day04/Solution.cs) | 2023-04 | Completed |
+| [Trebuchet?!](https://adventofcode.com/2023/day/1) | [Solution](./src/AdventOfCode/Calendar/2023/Day01/Solution.cs) | 2023-01 | Completed |
+| [Cube Conundrum](https://adventofcode.com/2023/day/2) | [Solution](./src/AdventOfCode/Calendar/2023/Day02/Solution.cs) | 2023-02 | Completed |
+| [Gear Ratios](https://adventofcode.com/2023/day/3) | [Solution](./src/AdventOfCode/Calendar/2023/Day03/Solution.cs) | 2023-03 | Incomplete |
+| [Scratchcards](https://adventofcode.com/2023/day/4) | [Solution](./src/AdventOfCode/Calendar/2023/Day04/Solution.cs) | 2023-04 | Completed |
diff --git a/src/AdventOfCode/AdventOfCode.csproj b/src/AdventOfCode/AdventOfCode.csproj
new file mode 100644
index 0000000..287cdc0
--- /dev/null
+++ b/src/AdventOfCode/AdventOfCode.csproj
@@ -0,0 +1,16 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
+
+ Always
+
+
+
+
diff --git a/AdventOfCode/Calendar/2023/Day01/Solution.cs b/src/AdventOfCode/Calendar/2023/Day01/Solution.cs
similarity index 93%
rename from AdventOfCode/Calendar/2023/Day01/Solution.cs
rename to src/AdventOfCode/Calendar/2023/Day01/Solution.cs
index 98f1d6c..8eee5d1 100644
--- a/AdventOfCode/Calendar/2023/Day01/Solution.cs
+++ b/src/AdventOfCode/Calendar/2023/Day01/Solution.cs
@@ -1,6 +1,6 @@
namespace AdventOfCode.Calendar._2023.Day01;
-internal class Solution : BaseSolution
+public class Solution : BaseSolution
{
private static readonly Dictionary _numberWords = new()
{
@@ -32,11 +32,8 @@ public override async Task Run(RunMode runMode)
/// represent the tens place. The last number will be the ones place.
///
private static int SumCalibrationValues(string[] inputLines) =>
- inputLines.Sum(line =>
- {
- return 10 * AsNumber(line.First(char.IsDigit)) +
- AsNumber(line.Last(char.IsDigit));
- });
+ inputLines.Sum(line => 10 * AsNumber(line.First(char.IsDigit)) +
+ AsNumber(line.Last(char.IsDigit)));
///
/// Make two passes against the line: forward from beginning to end looking
diff --git a/AdventOfCode/Calendar/2023/Day01/input.txt b/src/AdventOfCode/Calendar/2023/Day01/input.txt
similarity index 100%
rename from AdventOfCode/Calendar/2023/Day01/input.txt
rename to src/AdventOfCode/Calendar/2023/Day01/input.txt
diff --git a/src/AdventOfCode/Calendar/2023/Day02/SetOfCubes.cs b/src/AdventOfCode/Calendar/2023/Day02/SetOfCubes.cs
new file mode 100644
index 0000000..32d1c27
--- /dev/null
+++ b/src/AdventOfCode/Calendar/2023/Day02/SetOfCubes.cs
@@ -0,0 +1,22 @@
+using System.Reflection;
+
+namespace AdventOfCode.Calendar._2023.Day02;
+
+public sealed class SetOfCubes()
+{
+ public int Red { get; set; }
+ public int Green { get; set; }
+ public int Blue { get; set; }
+
+#pragma warning disable S1144 // Unused private types or members should be removed
+ public int this[string colorName]
+#pragma warning restore S1144 // Unused private types or members should be removed
+ {
+ set
+ {
+ GetType()
+ .GetProperty(colorName, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public)
+ !.SetValue(this, value, null);
+ }
+ }
+}
diff --git a/AdventOfCode/Calendar/2023/Day02/Solution.cs b/src/AdventOfCode/Calendar/2023/Day02/Solution.cs
similarity index 69%
rename from AdventOfCode/Calendar/2023/Day02/Solution.cs
rename to src/AdventOfCode/Calendar/2023/Day02/Solution.cs
index 33c7bae..c38b9c9 100644
--- a/AdventOfCode/Calendar/2023/Day02/Solution.cs
+++ b/src/AdventOfCode/Calendar/2023/Day02/Solution.cs
@@ -1,8 +1,6 @@
-using System.Reflection;
+namespace AdventOfCode.Calendar._2023.Day02;
-namespace AdventOfCode.Calendar._2023.Day02;
-
-internal class Solution : BaseSolution
+public class Solution : BaseSolution
{
private readonly SetOfCubes _constraint = new()
{
@@ -11,25 +9,6 @@ internal class Solution : BaseSolution
Blue = 14
};
- private sealed class SetOfCubes()
- {
- public int Red { get; set; }
- public int Green { get; set; }
- public int Blue { get; set; }
-
-#pragma warning disable S1144 // Unused private types or members should be removed
- public int this[string colorName]
-#pragma warning restore S1144 // Unused private types or members should be removed
- {
- set
- {
- GetType()
- .GetProperty(colorName, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public)
- !.SetValue(this, value, null);
- }
- }
- }
-
public override async Task Run(RunMode runMode)
{
var lines = await ReadInput();
@@ -65,9 +44,9 @@ private static int SumPowerSets(string[] lines)
{
var sum = 0;
- for (var gameId = 0; gameId < lines.Length; gameId++)
+ foreach (var line in lines)
{
- var sets = SetsInGame(lines[gameId]);
+ var sets = SetsInGame(line);
sum += sets.Max(x => x.Red) * sets.Max(x => x.Green) * sets.Max(x => x.Blue);
}
diff --git a/AdventOfCode/Calendar/2023/Day02/input.txt b/src/AdventOfCode/Calendar/2023/Day02/input.txt
similarity index 100%
rename from AdventOfCode/Calendar/2023/Day02/input.txt
rename to src/AdventOfCode/Calendar/2023/Day02/input.txt
diff --git a/AdventOfCode/Calendar/2023/Day03/Solution.cs b/src/AdventOfCode/Calendar/2023/Day03/Solution.cs
similarity index 94%
rename from AdventOfCode/Calendar/2023/Day03/Solution.cs
rename to src/AdventOfCode/Calendar/2023/Day03/Solution.cs
index 3aff36a..23b1f74 100644
--- a/AdventOfCode/Calendar/2023/Day03/Solution.cs
+++ b/src/AdventOfCode/Calendar/2023/Day03/Solution.cs
@@ -11,7 +11,7 @@ namespace AdventOfCode.Calendar._2023.Day03;
/// than implementing algorithms from scratch [poorly] -- this really showed
/// for part 2.
///
-internal partial class Solution : BaseSolution
+public partial class Solution : BaseSolution
{
private const char PeriodSymbol = '.';
private const char GearSymbol = '*';
@@ -74,7 +74,7 @@ private int SumGearRatios()
_lines[lineNumber][match.Index - 2] != PeriodSymbol &&
!seen.Exists(x => x.Value == match.Value))
{
- var rl = GearRatioRLRegex();
+ var rl = GearRatioRightLeftRegex();
var rlMatches = rl.Match(_lines[lineNumber], match.Index);
if (rlMatches.Success)
@@ -89,7 +89,7 @@ private int SumGearRatios()
if (boundingBox[(int)Direction.Right].Contains(GearSymbol) &&
_lines[lineNumber][match.Index + match.Value.Length + 1] != PeriodSymbol)
{
- var lr = GearRatioLRRegex();
+ var lr = GearRatioLeftRightRegex();
var rlMatches = lr.Match(_lines[lineNumber], match.Index + match.Value.Length);
if (rlMatches.Success)
@@ -110,8 +110,8 @@ private int SumGearRatios()
// to the right and left of it then concatenate them to
// get the part number.
- var lr = GearRatioLRRegex();
- var rl = GearRatioRLRegex();
+ var lr = GearRatioLeftRightRegex();
+ var rl = GearRatioRightLeftRegex();
var lrMatches = lr.Match(_lines[lineNumber + 2], match.Index + gearPosition);
var rlMatches = rl.Match(_lines[lineNumber + 2], match.Index + gearPosition);
@@ -199,8 +199,8 @@ private string[] GetBoundingBox(int currentLine, int matchIndex, string number)
private static partial Regex NumberRegex();
[GeneratedRegex(@"\d+")]
- private static partial Regex GearRatioLRRegex();
+ private static partial Regex GearRatioLeftRightRegex();
[GeneratedRegex(@"\d+", RegexOptions.RightToLeft)]
- private static partial Regex GearRatioRLRegex();
+ private static partial Regex GearRatioRightLeftRegex();
}
diff --git a/AdventOfCode/Calendar/2023/Day03/input.txt b/src/AdventOfCode/Calendar/2023/Day03/input.txt
similarity index 100%
rename from AdventOfCode/Calendar/2023/Day03/input.txt
rename to src/AdventOfCode/Calendar/2023/Day03/input.txt
diff --git a/src/AdventOfCode/Calendar/2023/Day04/Scratchcard.cs b/src/AdventOfCode/Calendar/2023/Day04/Scratchcard.cs
new file mode 100644
index 0000000..fb5a655
--- /dev/null
+++ b/src/AdventOfCode/Calendar/2023/Day04/Scratchcard.cs
@@ -0,0 +1,8 @@
+namespace AdventOfCode.Calendar._2023.Day04;
+
+public class Scratchcard
+{
+ public IEnumerable WinningNumbers { get; set; } = Enumerable.Empty();
+ public IEnumerable MyNumbers { get; set; } = Enumerable.Empty();
+ public int Worth => (int)Math.Pow(2, WinningNumbers.Count() - 1);
+}
diff --git a/AdventOfCode/Calendar/2023/Day04/Solution.cs b/src/AdventOfCode/Calendar/2023/Day04/Solution.cs
similarity index 85%
rename from AdventOfCode/Calendar/2023/Day04/Solution.cs
rename to src/AdventOfCode/Calendar/2023/Day04/Solution.cs
index 106fe49..c2c60f2 100644
--- a/AdventOfCode/Calendar/2023/Day04/Solution.cs
+++ b/src/AdventOfCode/Calendar/2023/Day04/Solution.cs
@@ -1,14 +1,7 @@
namespace AdventOfCode.Calendar._2023.Day04;
-internal class Solution : BaseSolution
+public class Solution : BaseSolution
{
- private class Scratchcard
- {
- public IEnumerable WinningNumbers { get; set; } = Enumerable.Empty();
- public IEnumerable MyNumbers { get; set; } = Enumerable.Empty();
- public int Worth => (int)Math.Pow(2, WinningNumbers.Count() - 1);
- }
-
public override async Task Run(RunMode runMode)
{
var scratchcards = await CountCards();
diff --git a/AdventOfCode/Calendar/2023/Day04/input.txt b/src/AdventOfCode/Calendar/2023/Day04/input.txt
similarity index 100%
rename from AdventOfCode/Calendar/2023/Day04/input.txt
rename to src/AdventOfCode/Calendar/2023/Day04/input.txt
diff --git a/AdventOfCode/Calendar/BaseSolution.cs b/src/AdventOfCode/Calendar/BaseSolution.cs
similarity index 95%
rename from AdventOfCode/Calendar/BaseSolution.cs
rename to src/AdventOfCode/Calendar/BaseSolution.cs
index 1e3ab5c..c685d83 100644
--- a/AdventOfCode/Calendar/BaseSolution.cs
+++ b/src/AdventOfCode/Calendar/BaseSolution.cs
@@ -12,7 +12,7 @@ public abstract class BaseSolution
/// Input file will reside in a subdirectory of the executable. That
/// path will follow the same as the namespace mostly.
///
- public virtual async Task ReadInput()
+ protected virtual async Task ReadInput()
{
var solutionDirectory = GetType().Namespace!
.Replace(nameof(AdventOfCode), string.Empty)
diff --git a/AdventOfCode/Program.cs b/src/AdventOfCode/Program.cs
similarity index 100%
rename from AdventOfCode/Program.cs
rename to src/AdventOfCode/Program.cs
diff --git a/AdventOfCode/RunMode.cs b/src/AdventOfCode/RunMode.cs
similarity index 100%
rename from AdventOfCode/RunMode.cs
rename to src/AdventOfCode/RunMode.cs
diff --git a/AdventOfCode/AdventOfCode.csproj b/tests/AdventOfCode.Tests/AdventOfCode.Tests.csproj
similarity index 53%
rename from AdventOfCode/AdventOfCode.csproj
rename to tests/AdventOfCode.Tests/AdventOfCode.Tests.csproj
index 2d7889b..aeebfd8 100644
--- a/AdventOfCode/AdventOfCode.csproj
+++ b/tests/AdventOfCode.Tests/AdventOfCode.Tests.csproj
@@ -1,26 +1,28 @@
-
+
- Exe
net8.0
enable
enable
- false
+ false
+ true
-
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
all
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
-
- Always
-
+
diff --git a/AdventOfCode/Calendar/2023/Day01/SolutionTests.cs b/tests/AdventOfCode.Tests/Calendar/2023/Day01/SolutionTests.cs
similarity index 82%
rename from AdventOfCode/Calendar/2023/Day01/SolutionTests.cs
rename to tests/AdventOfCode.Tests/Calendar/2023/Day01/SolutionTests.cs
index c9d67cc..558fc32 100644
--- a/AdventOfCode/Calendar/2023/Day01/SolutionTests.cs
+++ b/tests/AdventOfCode.Tests/Calendar/2023/Day01/SolutionTests.cs
@@ -1,12 +1,13 @@
-using Xunit;
+using AdventOfCode.Calendar._2023.Day01;
+using Xunit;
-namespace AdventOfCode.Calendar._2023.Day01;
+namespace AdventOfCode.Tests.Calendar._2023.Day01;
public class SolutionTests
{
private class TestSolution(string[] inputLines) : Solution
{
- public override Task ReadInput() => Task.FromResult(inputLines);
+ protected override Task ReadInput() => Task.FromResult(inputLines);
}
[Fact]
diff --git a/AdventOfCode/Calendar/2023/Day02/SolutionTests.cs b/tests/AdventOfCode.Tests/Calendar/2023/Day02/SolutionTests.cs
similarity index 81%
rename from AdventOfCode/Calendar/2023/Day02/SolutionTests.cs
rename to tests/AdventOfCode.Tests/Calendar/2023/Day02/SolutionTests.cs
index 7c7b7d2..0145d2e 100644
--- a/AdventOfCode/Calendar/2023/Day02/SolutionTests.cs
+++ b/tests/AdventOfCode.Tests/Calendar/2023/Day02/SolutionTests.cs
@@ -1,12 +1,13 @@
-using Xunit;
+using AdventOfCode.Calendar._2023.Day02;
+using Xunit;
-namespace AdventOfCode.Calendar._2023.Day02;
+namespace AdventOfCode.Tests.Calendar._2023.Day02;
public class SolutionTests
{
private class TestSolution(string[] inputLines) : Solution
{
- public override Task ReadInput() => Task.FromResult(inputLines);
+ protected override Task ReadInput() => Task.FromResult(inputLines);
}
private readonly string[] _input =
diff --git a/AdventOfCode/Calendar/2023/Day03/SolutionTests.cs b/tests/AdventOfCode.Tests/Calendar/2023/Day03/SolutionTests.cs
similarity index 94%
rename from AdventOfCode/Calendar/2023/Day03/SolutionTests.cs
rename to tests/AdventOfCode.Tests/Calendar/2023/Day03/SolutionTests.cs
index 3397c83..cacc3fc 100644
--- a/AdventOfCode/Calendar/2023/Day03/SolutionTests.cs
+++ b/tests/AdventOfCode.Tests/Calendar/2023/Day03/SolutionTests.cs
@@ -1,12 +1,13 @@
-using Xunit;
+using AdventOfCode.Calendar._2023.Day03;
+using Xunit;
-namespace AdventOfCode.Calendar._2023.Day03;
+namespace AdventOfCode.Tests.Calendar._2023.Day03;
public class SolutionTests
{
private class TestSolution(string[] inputLines) : Solution
{
- public override Task ReadInput() => Task.FromResult(inputLines);
+ protected override Task ReadInput() => Task.FromResult(inputLines);
}
[Theory]
diff --git a/AdventOfCode/Calendar/2023/Day04/SolutionTests.cs b/tests/AdventOfCode.Tests/Calendar/2023/Day04/SolutionTests.cs
similarity index 81%
rename from AdventOfCode/Calendar/2023/Day04/SolutionTests.cs
rename to tests/AdventOfCode.Tests/Calendar/2023/Day04/SolutionTests.cs
index a00e281..1ec61d9 100644
--- a/AdventOfCode/Calendar/2023/Day04/SolutionTests.cs
+++ b/tests/AdventOfCode.Tests/Calendar/2023/Day04/SolutionTests.cs
@@ -1,12 +1,13 @@
-using Xunit;
+using AdventOfCode.Calendar._2023.Day04;
+using Xunit;
-namespace AdventOfCode.Calendar._2023.Day04;
+namespace AdventOfCode.Tests.Calendar._2023.Day04;
public class SolutionTests
{
private class TestSolution(string[] inputLines) : Solution
{
- public override Task ReadInput() => Task.FromResult(inputLines);
+ protected override Task ReadInput() => Task.FromResult(inputLines);
}
[Theory]