From 443e7385fda58e848a45c8a07624acce36133ed2 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Wed, 6 Dec 2023 18:55:14 -0600 Subject: [PATCH 1/4] chore: scaffold for day 6 puzzle --- 06/WaitForIt.Tests/GlobalUsings.cs | 2 ++ 06/WaitForIt.Tests/UnitTest1.cs | 10 ++++++++ 06/WaitForIt.Tests/WaitForIt.Tests.csproj | 30 +++++++++++++++++++++++ 06/WaitForIt/Program.cs | 2 ++ 06/WaitForIt/WaitForIt.csproj | 10 ++++++++ AdventOfCode2023.sln | 16 ++++++++++++ 6 files changed, 70 insertions(+) create mode 100644 06/WaitForIt.Tests/GlobalUsings.cs create mode 100644 06/WaitForIt.Tests/UnitTest1.cs create mode 100644 06/WaitForIt.Tests/WaitForIt.Tests.csproj create mode 100644 06/WaitForIt/Program.cs create mode 100644 06/WaitForIt/WaitForIt.csproj diff --git a/06/WaitForIt.Tests/GlobalUsings.cs b/06/WaitForIt.Tests/GlobalUsings.cs new file mode 100644 index 0000000..7fef4b0 --- /dev/null +++ b/06/WaitForIt.Tests/GlobalUsings.cs @@ -0,0 +1,2 @@ +global using Xunit; +global using FluentAssertions; \ No newline at end of file diff --git a/06/WaitForIt.Tests/UnitTest1.cs b/06/WaitForIt.Tests/UnitTest1.cs new file mode 100644 index 0000000..91eaf69 --- /dev/null +++ b/06/WaitForIt.Tests/UnitTest1.cs @@ -0,0 +1,10 @@ +namespace WaitForIt.Tests; + +public class UnitTest1 +{ + [Fact] + public void Test1() + { + + } +} \ No newline at end of file diff --git a/06/WaitForIt.Tests/WaitForIt.Tests.csproj b/06/WaitForIt.Tests/WaitForIt.Tests.csproj new file mode 100644 index 0000000..6a16e89 --- /dev/null +++ b/06/WaitForIt.Tests/WaitForIt.Tests.csproj @@ -0,0 +1,30 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/06/WaitForIt/Program.cs b/06/WaitForIt/Program.cs new file mode 100644 index 0000000..3751555 --- /dev/null +++ b/06/WaitForIt/Program.cs @@ -0,0 +1,2 @@ +// See https://aka.ms/new-console-template for more information +Console.WriteLine("Hello, World!"); diff --git a/06/WaitForIt/WaitForIt.csproj b/06/WaitForIt/WaitForIt.csproj new file mode 100644 index 0000000..2150e37 --- /dev/null +++ b/06/WaitForIt/WaitForIt.csproj @@ -0,0 +1,10 @@ + + + + Exe + net8.0 + enable + enable + + + diff --git a/AdventOfCode2023.sln b/AdventOfCode2023.sln index 2c0a187..8590e39 100644 --- a/AdventOfCode2023.sln +++ b/AdventOfCode2023.sln @@ -33,6 +33,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IYGASAF", "05\IYGASAF\IYGAS EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IYGASAF.Tests", "05\IYGASAF.Tests\IYGASAF.Tests.csproj", "{CB90004D-9420-4411-9110-B50274537FE5}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "06", "06", "{86704890-D6B8-4166-853B-F1424B8396C7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WaitForIt", "06\WaitForIt\WaitForIt.csproj", "{B3D736D4-EFEE-44AA-B199-1A1C803F1793}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WaitForIt.Tests", "06\WaitForIt.Tests\WaitForIt.Tests.csproj", "{8C89E1D0-2617-4B89-BA9C-9189FC69BC43}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -82,6 +88,14 @@ Global {CB90004D-9420-4411-9110-B50274537FE5}.Debug|Any CPU.Build.0 = Debug|Any CPU {CB90004D-9420-4411-9110-B50274537FE5}.Release|Any CPU.ActiveCfg = Release|Any CPU {CB90004D-9420-4411-9110-B50274537FE5}.Release|Any CPU.Build.0 = Release|Any CPU + {B3D736D4-EFEE-44AA-B199-1A1C803F1793}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B3D736D4-EFEE-44AA-B199-1A1C803F1793}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B3D736D4-EFEE-44AA-B199-1A1C803F1793}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B3D736D4-EFEE-44AA-B199-1A1C803F1793}.Release|Any CPU.Build.0 = Release|Any CPU + {8C89E1D0-2617-4B89-BA9C-9189FC69BC43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8C89E1D0-2617-4B89-BA9C-9189FC69BC43}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8C89E1D0-2617-4B89-BA9C-9189FC69BC43}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8C89E1D0-2617-4B89-BA9C-9189FC69BC43}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {3F8EAC09-4BC7-43AA-B72B-48DDD2710F6D} = {8C29858C-623A-461A-BF0B-254E151CD9C2} @@ -94,5 +108,7 @@ Global {FF8A5512-85FD-45E7-9F97-EC528465949C} = {522D6D1E-54AD-4479-BB78-0AB5D7493EFC} {417E0408-31C8-4945-B684-5004233D6AF4} = {5067FD6B-8F03-4502-AB83-8A391D801B47} {CB90004D-9420-4411-9110-B50274537FE5} = {5067FD6B-8F03-4502-AB83-8A391D801B47} + {B3D736D4-EFEE-44AA-B199-1A1C803F1793} = {86704890-D6B8-4166-853B-F1424B8396C7} + {8C89E1D0-2617-4B89-BA9C-9189FC69BC43} = {86704890-D6B8-4166-853B-F1424B8396C7} EndGlobalSection EndGlobal From 6462fd802722d8ffa7ed5dfdd1d5745476e77457 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Wed, 6 Dec 2023 20:21:11 -0600 Subject: [PATCH 2/4] feat: solve part 1 and part 2 of puzzle 6 --- 06/WaitForIt.Tests/ProgramTests.cs | 16 +++ 06/WaitForIt.Tests/PuzzleParserTests.cs | 38 +++++++ 06/WaitForIt.Tests/RaceTests.cs | 14 +++ 06/WaitForIt.Tests/UnitTest1.cs | 10 -- 06/WaitForIt.Tests/WaitForIt.Tests.csproj | 6 + 06/WaitForIt/Program.cs | 129 +++++++++++++++++++++- 6 files changed, 201 insertions(+), 12 deletions(-) create mode 100644 06/WaitForIt.Tests/ProgramTests.cs create mode 100644 06/WaitForIt.Tests/PuzzleParserTests.cs create mode 100644 06/WaitForIt.Tests/RaceTests.cs delete mode 100644 06/WaitForIt.Tests/UnitTest1.cs diff --git a/06/WaitForIt.Tests/ProgramTests.cs b/06/WaitForIt.Tests/ProgramTests.cs new file mode 100644 index 0000000..0159c46 --- /dev/null +++ b/06/WaitForIt.Tests/ProgramTests.cs @@ -0,0 +1,16 @@ +namespace WaitForIt.Tests; + +public class ProgramTests +{ + public void Main_WhenGivenInput_ItShouldReturnTheProductOfTheMarginOfErrors() + { + var result = Program.Main(["INPUT.txt"]); + result.Should().Be(1710720); + } + + public void Main_WhenGivenInputAndPart2_ItShouldReturnTheNumberOfWaysToWin() + { + var result = Program.Main(["INPUT.txt", "part2"]); + result.Should().Be(35349468); + } +} \ No newline at end of file diff --git a/06/WaitForIt.Tests/PuzzleParserTests.cs b/06/WaitForIt.Tests/PuzzleParserTests.cs new file mode 100644 index 0000000..c992a3e --- /dev/null +++ b/06/WaitForIt.Tests/PuzzleParserTests.cs @@ -0,0 +1,38 @@ +namespace WaitForIt.Tests; + +public class PuzzleParserTests +{ + private readonly PuzzleParser _sut = new(); + + [Theory] + [MemberData(nameof(TestData.ValidInputData), MemberType = typeof(TestData))] + public void Parse_WhenGivenValidInput_ItShouldReturnAListOfRaces(string[] input, List expected) + { + var result = _sut.ParseRaces(input); + result.Should().BeEquivalentTo(expected); + } + + public static class TestData + { + private static readonly string[] ValidInput = + [ + "Time: 7 15 30", + "Distance: 9 40 200" + ]; + + public static IEnumerable ValidInputData => + new List + { + new object[] + { + ValidInput, + new List + { + new(7, 9), + new(15, 40), + new(30, 200) + } + } + }; + } +} \ No newline at end of file diff --git a/06/WaitForIt.Tests/RaceTests.cs b/06/WaitForIt.Tests/RaceTests.cs new file mode 100644 index 0000000..91c33ad --- /dev/null +++ b/06/WaitForIt.Tests/RaceTests.cs @@ -0,0 +1,14 @@ +namespace WaitForIt.Tests; + +public class RaceTests +{ + [Theory] + [InlineData(7, 9, 4)] + [InlineData(15, 40, 8)] + [InlineData(30, 200, 9)] + public void CalculateNumberOfWaysToWin_WhenCalled_ItShouldReturnNumberOfWaysToWin(int raceDuration, int distanceRecord, int expected) + { + var result = new Race(raceDuration, distanceRecord).CalculateNumberOfWaysToWin(); + result.Should().Be(expected); + } +} \ No newline at end of file diff --git a/06/WaitForIt.Tests/UnitTest1.cs b/06/WaitForIt.Tests/UnitTest1.cs deleted file mode 100644 index 91eaf69..0000000 --- a/06/WaitForIt.Tests/UnitTest1.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace WaitForIt.Tests; - -public class UnitTest1 -{ - [Fact] - public void Test1() - { - - } -} \ No newline at end of file diff --git a/06/WaitForIt.Tests/WaitForIt.Tests.csproj b/06/WaitForIt.Tests/WaitForIt.Tests.csproj index 6a16e89..0647535 100644 --- a/06/WaitForIt.Tests/WaitForIt.Tests.csproj +++ b/06/WaitForIt.Tests/WaitForIt.Tests.csproj @@ -27,4 +27,10 @@ + + + PreserveNewest + + + diff --git a/06/WaitForIt/Program.cs b/06/WaitForIt/Program.cs index 3751555..c6c8015 100644 --- a/06/WaitForIt/Program.cs +++ b/06/WaitForIt/Program.cs @@ -1,2 +1,127 @@ -// See https://aka.ms/new-console-template for more information -Console.WriteLine("Hello, World!"); +namespace WaitForIt; + +public class Program +{ + public static async Task Main(string[] args) + { + if (args.Length is 0) + { + Console.WriteLine("Please provide a path to the input file."); + return -1; + } + + if (File.Exists(args[0]) is false) + { + Console.WriteLine("The provided file does not exist."); + return -2; + } + + var parser = new PuzzleParser(); + var input = await File.ReadAllLinesAsync(args[0]); + + long result = args.Length > 1 && args[1] == "part2" + ? parser + .ParseRace(input) + .CalculateNumberOfWaysToWin() + : parser.ParseRaces(input) + .Select(r => r.CalculateNumberOfWaysToWin()) + .Aggregate((long)1, (acc, curr) => acc * curr); + + Console.WriteLine($"The product of the margin of errors is {result}."); + + return (int)result; + } +} + +/// +/// Parses the puzzle input. +/// +public class PuzzleParser +{ + private List GetValues(string input) => input + .Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) + .Skip(1) + .Select(long.Parse) + .ToList(); + + /// + /// Parses the puzzle input to list of races + /// + /// The list of races + /// A list containing instances of . + public List ParseRaces(string[] racesInput) + { + var races = new List(); + var durations = GetValues(racesInput[0]); + var distances = GetValues(racesInput[1]); + + if (durations.Count != distances.Count) + { + throw new ArgumentException("The number of times and distances must be equal."); + } + + for (int i = 0; i < durations.Count; i++) + { + races.Add(new Race(durations[i], distances[i])); + } + + return races; + } + + /// + /// Parses the puzzle input as single race + /// + /// The list of races + /// An instance of . + public Race ParseRace(string[] racesInput) + { + var duration = string.Join("", GetValues(racesInput[0]).Select(v => v.ToString())); + var distance = string.Join("", GetValues(racesInput[1]).Select(v => v.ToString())); + + return new Race(long.Parse(duration), long.Parse(distance)); + } +} + +/// +/// Represents a Race +/// +/// The duration of the race +/// The distance record +/// An instance of . +public class Race( + long duration, + long distanceRecord +) +{ + /// + /// Gets the duration of the race + /// + public long Duration { get; init; } = duration; + + /// + /// Gets the distance record + /// + public long DistanceRecord { get; init; } = distanceRecord; + + /// + /// Calculates the number of ways the race can be won. + /// + /// The number of ways the race can be won. + public long CalculateNumberOfWaysToWin() + { + var numberOfWaysToWin = 0; + + for (var secsHeld = 0; secsHeld < Duration; secsHeld++) + { + var speed = 1 * secsHeld; + var distance = speed * (Duration - secsHeld); + + if (distance > DistanceRecord) + { + numberOfWaysToWin++; + } + } + + return numberOfWaysToWin; + } +} \ No newline at end of file From a0961bb9966cbc108a858b4b467c9b766f18e310 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Wed, 6 Dec 2023 20:29:56 -0600 Subject: [PATCH 3/4] fix: dry up --- 06/WaitForIt/Program.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/06/WaitForIt/Program.cs b/06/WaitForIt/Program.cs index c6c8015..e7fcf86 100644 --- a/06/WaitForIt/Program.cs +++ b/06/WaitForIt/Program.cs @@ -18,8 +18,9 @@ public class Program var parser = new PuzzleParser(); var input = await File.ReadAllLinesAsync(args[0]); + var isPart2 = args.Length > 1 && args[1] == "part2"; - long result = args.Length > 1 && args[1] == "part2" + long result = isPart2 ? parser .ParseRace(input) .CalculateNumberOfWaysToWin() @@ -27,7 +28,14 @@ public class Program .Select(r => r.CalculateNumberOfWaysToWin()) .Aggregate((long)1, (acc, curr) => acc * curr); - Console.WriteLine($"The product of the margin of errors is {result}."); + if (isPart2) + { + Console.WriteLine($"The number of ways to win is {result}."); + } + else + { + Console.WriteLine($"The total number of ways to win is {result}."); + } return (int)result; } From 539d1c3f093a6ab436e0e5e7a8faf2e7e932e28b Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Wed, 6 Dec 2023 20:30:37 -0600 Subject: [PATCH 4/4] chore: dotnet format --- 05/IYGASAF.Tests/GlobalUsings.cs | 2 +- 06/WaitForIt.Tests/GlobalUsings.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/05/IYGASAF.Tests/GlobalUsings.cs b/05/IYGASAF.Tests/GlobalUsings.cs index 2d5b473..d6f0167 100644 --- a/05/IYGASAF.Tests/GlobalUsings.cs +++ b/05/IYGASAF.Tests/GlobalUsings.cs @@ -1,3 +1,3 @@ global using FluentAssertions; -global using Xunit; +global using Xunit; \ No newline at end of file diff --git a/06/WaitForIt.Tests/GlobalUsings.cs b/06/WaitForIt.Tests/GlobalUsings.cs index 7fef4b0..2d5b473 100644 --- a/06/WaitForIt.Tests/GlobalUsings.cs +++ b/06/WaitForIt.Tests/GlobalUsings.cs @@ -1,2 +1,3 @@ +global using FluentAssertions; + global using Xunit; -global using FluentAssertions; \ No newline at end of file