From 3bd6ced4b71626e8a9091b434a39646f209bf37f Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Sat, 9 Dec 2023 00:57:51 -0600 Subject: [PATCH 1/8] chore: scaffold for day 9 puzzle --- 09/MirageMaintenance.Tests/GlobalUsings.cs | 2 ++ .../MirageMaintenance.Tests.csproj | 30 +++++++++++++++++++ 09/MirageMaintenance.Tests/UnitTest1.cs | 10 +++++++ 09/MirageMaintenance/MirageMaintenance.csproj | 10 +++++++ 09/MirageMaintenance/Program.cs | 2 ++ AdventOfCode2023.sln | 16 ++++++++++ 6 files changed, 70 insertions(+) create mode 100644 09/MirageMaintenance.Tests/GlobalUsings.cs create mode 100644 09/MirageMaintenance.Tests/MirageMaintenance.Tests.csproj create mode 100644 09/MirageMaintenance.Tests/UnitTest1.cs create mode 100644 09/MirageMaintenance/MirageMaintenance.csproj create mode 100644 09/MirageMaintenance/Program.cs diff --git a/09/MirageMaintenance.Tests/GlobalUsings.cs b/09/MirageMaintenance.Tests/GlobalUsings.cs new file mode 100644 index 0000000..7fef4b0 --- /dev/null +++ b/09/MirageMaintenance.Tests/GlobalUsings.cs @@ -0,0 +1,2 @@ +global using Xunit; +global using FluentAssertions; \ No newline at end of file diff --git a/09/MirageMaintenance.Tests/MirageMaintenance.Tests.csproj b/09/MirageMaintenance.Tests/MirageMaintenance.Tests.csproj new file mode 100644 index 0000000..589f7c5 --- /dev/null +++ b/09/MirageMaintenance.Tests/MirageMaintenance.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/09/MirageMaintenance.Tests/UnitTest1.cs b/09/MirageMaintenance.Tests/UnitTest1.cs new file mode 100644 index 0000000..561193c --- /dev/null +++ b/09/MirageMaintenance.Tests/UnitTest1.cs @@ -0,0 +1,10 @@ +namespace MirageMaintenance.Tests; + +public class UnitTest1 +{ + [Fact] + public void Test1() + { + + } +} \ No newline at end of file diff --git a/09/MirageMaintenance/MirageMaintenance.csproj b/09/MirageMaintenance/MirageMaintenance.csproj new file mode 100644 index 0000000..2150e37 --- /dev/null +++ b/09/MirageMaintenance/MirageMaintenance.csproj @@ -0,0 +1,10 @@ + + + + Exe + net8.0 + enable + enable + + + diff --git a/09/MirageMaintenance/Program.cs b/09/MirageMaintenance/Program.cs new file mode 100644 index 0000000..3751555 --- /dev/null +++ b/09/MirageMaintenance/Program.cs @@ -0,0 +1,2 @@ +// See https://aka.ms/new-console-template for more information +Console.WriteLine("Hello, World!"); diff --git a/AdventOfCode2023.sln b/AdventOfCode2023.sln index bc2abf3..f963b6c 100644 --- a/AdventOfCode2023.sln +++ b/AdventOfCode2023.sln @@ -51,6 +51,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HauntedWasteland", "08\Haun EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HauntedWasteland.Tests", "08\HauntedWasteland.Tests\HauntedWasteland.Tests.csproj", "{FA8DDDD1-4DD9-4927-A9FB-C4FACDEAF901}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "09", "09", "{79203C8D-F382-4C95-90EA-FECEE65602DA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MirageMaintenance", "09\MirageMaintenance\MirageMaintenance.csproj", "{6C233DE5-D1D0-46C0-A250-AF0272B495CE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MirageMaintenance.Tests", "09\MirageMaintenance.Tests\MirageMaintenance.Tests.csproj", "{5C39C115-ACBF-458A-9409-FBD23637A789}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -124,6 +130,14 @@ Global {FA8DDDD1-4DD9-4927-A9FB-C4FACDEAF901}.Debug|Any CPU.Build.0 = Debug|Any CPU {FA8DDDD1-4DD9-4927-A9FB-C4FACDEAF901}.Release|Any CPU.ActiveCfg = Release|Any CPU {FA8DDDD1-4DD9-4927-A9FB-C4FACDEAF901}.Release|Any CPU.Build.0 = Release|Any CPU + {6C233DE5-D1D0-46C0-A250-AF0272B495CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6C233DE5-D1D0-46C0-A250-AF0272B495CE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6C233DE5-D1D0-46C0-A250-AF0272B495CE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6C233DE5-D1D0-46C0-A250-AF0272B495CE}.Release|Any CPU.Build.0 = Release|Any CPU + {5C39C115-ACBF-458A-9409-FBD23637A789}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5C39C115-ACBF-458A-9409-FBD23637A789}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5C39C115-ACBF-458A-9409-FBD23637A789}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5C39C115-ACBF-458A-9409-FBD23637A789}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {3F8EAC09-4BC7-43AA-B72B-48DDD2710F6D} = {8C29858C-623A-461A-BF0B-254E151CD9C2} @@ -142,5 +156,7 @@ Global {8F04A78E-D2E1-41AC-B43C-74608B7B4FCB} = {7F8AD027-D8D7-407B-9E08-B363B7B34621} {332B56C1-8ECB-4E34-9E69-54BF6A192CFB} = {F21CCF39-1F8A-40DA-A0E5-F1426B09BAA2} {FA8DDDD1-4DD9-4927-A9FB-C4FACDEAF901} = {F21CCF39-1F8A-40DA-A0E5-F1426B09BAA2} + {6C233DE5-D1D0-46C0-A250-AF0272B495CE} = {79203C8D-F382-4C95-90EA-FECEE65602DA} + {5C39C115-ACBF-458A-9409-FBD23637A789} = {79203C8D-F382-4C95-90EA-FECEE65602DA} EndGlobalSection EndGlobal From 86fda4a81f662eac7876bb72ec0295fc42ee200c Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Sat, 9 Dec 2023 12:17:56 -0600 Subject: [PATCH 2/8] feat: start working on part 1 solution --- .../OasisReportTests.cs | 35 +++++++++ 09/MirageMaintenance.Tests/UnitTest1.cs | 10 --- .../ValueHistoryTests.cs | 76 +++++++++++++++++++ 09/MirageMaintenance/Program.cs | 73 +++++++++++++++++- 4 files changed, 182 insertions(+), 12 deletions(-) create mode 100644 09/MirageMaintenance.Tests/OasisReportTests.cs delete mode 100644 09/MirageMaintenance.Tests/UnitTest1.cs create mode 100644 09/MirageMaintenance.Tests/ValueHistoryTests.cs diff --git a/09/MirageMaintenance.Tests/OasisReportTests.cs b/09/MirageMaintenance.Tests/OasisReportTests.cs new file mode 100644 index 0000000..13b68cc --- /dev/null +++ b/09/MirageMaintenance.Tests/OasisReportTests.cs @@ -0,0 +1,35 @@ +namespace MirageMaintenance.Tests; + +public class UnitTest1 +{ + [Theory] + [MemberData(nameof(TestData.OasisReportParseTestData), MemberType = typeof(TestData))] + public void Parse_GivenAReportInput_ItShouldReturnExpectedOasisReportInstance(string[] input, OasisReport expected) + { + OasisReport.Parse(input).Should().BeEquivalentTo(expected); + } + + public static class TestData + { + public static IEnumerable OasisReportParseTestData => + new List + { + new object[] + { + new string[] + { + "0 3 6 9 12 15", + "1 3 6 10 15 21", + "10 13 16 21 30 45", + }, + new OasisReport( + [ + new([0, 3, 6, 9, 12, 15]), + new([1, 3, 6, 10, 15, 21]), + new([10, 13, 16, 21, 30, 45]), + ] + ) + } + }; + } +} \ No newline at end of file diff --git a/09/MirageMaintenance.Tests/UnitTest1.cs b/09/MirageMaintenance.Tests/UnitTest1.cs deleted file mode 100644 index 561193c..0000000 --- a/09/MirageMaintenance.Tests/UnitTest1.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace MirageMaintenance.Tests; - -public class UnitTest1 -{ - [Fact] - public void Test1() - { - - } -} \ No newline at end of file diff --git a/09/MirageMaintenance.Tests/ValueHistoryTests.cs b/09/MirageMaintenance.Tests/ValueHistoryTests.cs new file mode 100644 index 0000000..e2c2e8f --- /dev/null +++ b/09/MirageMaintenance.Tests/ValueHistoryTests.cs @@ -0,0 +1,76 @@ +namespace MirageMaintenance.Tests; + +public class ValueHistoryTests +{ + [Theory] + [MemberData(nameof(TestData.CalculateDifferencesTestData), MemberType = typeof(TestData))] + public void CalculateDifferences_GivenAListOfValues_ItShouldReturnAListOfDifferences(List values, List expected) + { + new ValueHistory([]).CalculateDifferences(values).Should().BeEquivalentTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.CalculateHistoryTest), MemberType = typeof(TestData))] + public void CalculateHistory_GivenAListOfValues_ItShouldReturnAListOfHistoricalValues(List values, List> expected) + { + new ValueHistory(values).CalculateHistory().Should().BeEquivalentTo(expected); + } + + public static class TestData + { + public static IEnumerable CalculateHistoryTest => + new List + { + new object[] + { + new List { 0, 3, 6, 9, 12, 15 }, + new List> + { + new() { 3, 3, 3, 3, 3 }, + new() { 0, 0, 0, 0 }, + }, + }, + new object[] + { + new List { 1, 3, 6, 10, 15, 21 }, + new List> + { + new() { 2, 3, 4, 5, 6 }, + new() { 1, 1, 1, 1 }, + new() { 0, 0, 0 }, + }, + }, + new object[] + { + new List { 10, 13, 16, 21, 30, 45 }, + new List> + { + new() { 3, 3, 5, 9, 15 }, + new() { 0, 2, 4, 6 }, + new() { 2, 2, 2 }, + new() { 0, 0 }, + }, + }, + }; + + public static IEnumerable CalculateDifferencesTestData => + new List + { + new object[] + { + new List { 0, 3, 6, 9, 12, 15 }, + new List { 3, 3, 3, 3, 3 }, + }, + new object[] + { + new List { 1, 3, 6, 10, 15, 21 }, + new List { 2, 3, 4, 5, 6 }, + }, + new object[] + { + new List { 10, 13, 16, 21, 30, 45 }, + new List { 3, 3, 5, 9, 15 }, + }, + }; + } +} \ No newline at end of file diff --git a/09/MirageMaintenance/Program.cs b/09/MirageMaintenance/Program.cs index 3751555..3a825bd 100644 --- a/09/MirageMaintenance/Program.cs +++ b/09/MirageMaintenance/Program.cs @@ -1,2 +1,71 @@ -// See https://aka.ms/new-console-template for more information -Console.WriteLine("Hello, World!"); +namespace MirageMaintenance; + +class Program +{ + public static async Task Main(string[] args) + { + return await Task.FromResult(0); + } +} + +public class OasisReport( + List valueHistories +) +{ + public List ValueHistories { get; init; } = valueHistories; + + public static OasisReport Parse(string[] oasisReportInput) + { + var valueHistories = new List(); + + foreach (var line in oasisReportInput) + { + var values = line + .Split(' ', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries) + .Select(long.Parse) + .ToList(); + + var valueHistory = new ValueHistory(values); + valueHistories.Add(valueHistory); + } + + return new OasisReport(valueHistories); + } +} + +public class ValueHistory( + List values +) +{ + List Values { get; init; } = values; + + public List CalculateDifferences(List values) => Enumerable + .Range(0, values.Count - 1) + .Select(i => values[i + 1] - values[i]) + .ToList(); + + public List> CalculateHistory() + { + var allHistoricalValues = new List>(); + var currentValues = Values; + + while ( + allHistoricalValues.Count is 0 || + allHistoricalValues.Last().Sum() is not 0 + ) + { + var historicalValues = CalculateDifferences(currentValues); + allHistoricalValues.Add(historicalValues); + currentValues = historicalValues; + } + + return allHistoricalValues; + } + + public long CalculateNextValue() + { + var historicalValues = CalculateHistory(); + var values = historicalValues.Prepend(Values).ToList(); + return 0; + } +} \ No newline at end of file From 8727f9e4698b89449577ed0128b140af2d2208c6 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Sat, 9 Dec 2023 20:55:02 -0600 Subject: [PATCH 3/8] feat: solve part 1...summing to zero is bad check when neg nums are present --- .../MirageMaintenance.Tests.csproj | 6 + .../OasisReportTests.cs | 13 ++ .../ValueHistoryTests.cs | 148 +++++++++++++++++- 09/MirageMaintenance/Program.cs | 55 ++++++- 4 files changed, 215 insertions(+), 7 deletions(-) diff --git a/09/MirageMaintenance.Tests/MirageMaintenance.Tests.csproj b/09/MirageMaintenance.Tests/MirageMaintenance.Tests.csproj index 589f7c5..52a586c 100644 --- a/09/MirageMaintenance.Tests/MirageMaintenance.Tests.csproj +++ b/09/MirageMaintenance.Tests/MirageMaintenance.Tests.csproj @@ -27,4 +27,10 @@ + + + PreserveNewest + + + diff --git a/09/MirageMaintenance.Tests/OasisReportTests.cs b/09/MirageMaintenance.Tests/OasisReportTests.cs index 13b68cc..d3ffdb3 100644 --- a/09/MirageMaintenance.Tests/OasisReportTests.cs +++ b/09/MirageMaintenance.Tests/OasisReportTests.cs @@ -9,6 +9,19 @@ public class UnitTest1 OasisReport.Parse(input).Should().BeEquivalentTo(expected); } + [Fact] + public void CalculateSumOfNextValues_GivenAReportInput_ItShouldReturnTheSumOfAllNextValues() + { + var input = new string[] + { + "0 3 6 9 12 15", + "1 3 6 10 15 21", + "10 13 16 21 30 45", + }; + + OasisReport.Parse(input).CalculateSumOfNextValues().Should().Be(114); + } + public static class TestData { public static IEnumerable OasisReportParseTestData => diff --git a/09/MirageMaintenance.Tests/ValueHistoryTests.cs b/09/MirageMaintenance.Tests/ValueHistoryTests.cs index e2c2e8f..df7382a 100644 --- a/09/MirageMaintenance.Tests/ValueHistoryTests.cs +++ b/09/MirageMaintenance.Tests/ValueHistoryTests.cs @@ -10,15 +10,107 @@ public class ValueHistoryTests } [Theory] - [MemberData(nameof(TestData.CalculateHistoryTest), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.CalculateHistoryTestData), MemberType = typeof(TestData))] public void CalculateHistory_GivenAListOfValues_ItShouldReturnAListOfHistoricalValues(List values, List> expected) { new ValueHistory(values).CalculateHistory().Should().BeEquivalentTo(expected); } + [Theory] + [MemberData(nameof(TestData.CalculateNextValueTestData), MemberType = typeof(TestData))] + public void CalculateNextValue_GivenAListOfValues_ItShouldReturnTheNextValue(List values, long expected) + { + new ValueHistory(values).CalculateNextValue().Should().Be(expected); + } + public static class TestData { - public static IEnumerable CalculateHistoryTest => + public static IEnumerable CalculateNextValueTestData => + new List + { + new object[] + { + new List { 0, 3, 6, 9, 12, 15 }, + 18, + }, + new object[] + { + new List { 1, 3, 6, 10, 15, 21 }, + 28, + }, + new object[] + { + new List { 10, 13, 16, 21, 30, 45 }, + 68, + }, + new object[] + { + new List { -7, 6, 44, 130, 309, 672, 1404, 2864, 5712, 11113, 21082, 39112, 71386, 129156, 233312, 422773, 769075, 1400300, 2538072, 4551386, 8029995 }, + 13877188, + }, + new object[] + { + new List { 5, 13, 45, 115, 234, 420, 731, 1329, 2591, 5314, 11131, 23388, 48974, 102035, 211293, 434077, 882526, 1771333, 3502944, 6817585, 13056927 }, + 24632652 + }, + new object[] + { + new List { 12, 34, 63, 97, 134, 172, 209, 243, 272, 294, 307, 309, 298, 272, 229, 167, 84, -22, -153, -311, -498 }, + -716, + }, + new object[] + { + new List { 0, 8, 26, 57, 105, 173, 258, 346, 429, 605, 1397, 4561, 14876, 43758, 116059, 282152, 638422, 1360646, 2756524, 5345897, 9980043 }, + 18014971, + }, + new object[] + { + new List { 8, 29, 72, 144, 248, 390, 605, 1026, 2039, 4596, 10807, 25025, 55832, 119755, 248445, 502919, 1002134, 1980015, 3897262, 7655070, 14992036 }, + 29199652, + }, + new object[] + { + new List { 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7 }, + -8, + }, + new object[] + { + new List { -6, -13, -22, -33, -46, -61, -78, -97, -118, -141, -166, -193, -222, -253, -286, -321, -358, -397, -438, -481, -526 }, + -573 + }, + new object[] + { + new List { 9, 27, 56, 112, 226, 457, 930, 1921, 4030, 8514, 17905, 37139, 75621, 151030, 296349, 572758, 1092879, 2061701, 3846702, 7094666, 12920996 }, + 23208575, + }, + new object[] + { + new List { -3, -1, 14, 61, 171, 389, 774, 1400, 2372, 3888, 6401, 10974, 20014, 38812, 78893, 165423, 353359, 761461, 1640856, 3507131, 7384045 }, + 15235639, + }, + new object[] + { + new List { 11, 29, 63, 133, 274, 553, 1096, 2121, 3987, 7294, 13115, 23530, 42796, 79765, 152604, 297574, 584852, 1146848, 2229936, 4292852, 8201987 }, + 15629938, + }, + new object[] + { + new List { 4, 16, 45, 98, 187, 334, 576, 970, 1598, 2572, 4039, 6186, 9245, 13498, 19282, 26994, 37096, 50120, 66673, 87442, 113199 }, + 144806, + }, + new object[] + { + new List { 8, 20, 57, 137, 294, 600, 1198, 2360, 4606, 8946, 17345, 33579, 64776, 124157, 235847, 443145, 822344, 1505117, 2713796, 4816071, 8409952 }, + 14458829, + }, + new object[] + { + new List { 13, 16, 31, 72, 171, 391, 853, 1788, 3635, 7233, 14219, 27894, 55158, 110850, 227371, 475612, 1009429, 2157809, 4610859, 9784975, 20520225 }, + 42376168 + } + }; + + public static IEnumerable CalculateHistoryTestData => new List { new object[] @@ -51,6 +143,53 @@ public class ValueHistoryTests new() { 0, 0 }, }, }, + new object[] + { + new List { -7, 6, 44, 130, 309, 672, 1404, 2864, 5712, 11113, 21082, 39112, 71386, 129156, 233312, 422773, 769075, 1400300, 2538072, 4551386, 8029995 }, + new List> + { + new() { 13, 38, 86, 179, 363, 732, 1460, 2848, 5401, 9969, 18030, 32274, 57770, 104156, 189461, 346302, 631225, 1137772, 2013314, 3478609 }, + new() { 25, 48, 93, 184, 369, 728, 1388, 2553, 4568, 8061, 14244, 25496, 46386, 85305, 156841, 284923, 506547, 875542, 1465295 }, + new() { 23, 45, 91, 185, 359, 660, 1165, 2015, 3493, 6183, 11252, 20890, 38919, 71536, 128082, 221624, 368995, 589753 }, + new() { 22, 46, 94, 174, 301, 505, 850, 1478, 2690, 5069, 9638, 18029, 32617, 56546, 93542, 147371, 220758 }, + new() { 24, 48, 80, 127, 204, 345, 628, 1212, 2379, 4569, 8391, 14588, 23929, 36996, 53829, 73387 }, + new() { 24, 32, 47, 77, 141, 283, 584, 1167, 2190, 3822, 6197, 9341, 13067, 16833, 19558 }, + new() { 8, 15, 30, 64, 142, 301, 583, 1023, 1632, 2375, 3144, 3726, 3766, 2725 }, + new() { 7, 15, 34, 78, 159, 282, 440, 609, 743, 769, 582, 40, -1041 }, + new() { 8, 19, 44, 81, 123, 158, 169, 134, 26, -187, -542, -1081 }, + new() { 11, 25, 37, 42, 35, 11, -35, -108, -213, -355, -539 }, + new() { 14, 12, 5, -7, -24, -46, -73, -105, -142, -184 }, + new() { -2, -7, -12, -17, -22, -27, -32, -37, -42 }, + new() { -5, -5, -5, -5, -5, -5, -5, -5 }, + new() { 0, 0, 0, 0, 0, 0, 0 }, + } + }, + new object[] + { + new List { 8, 20, 57, 137, 294, 600, 1198, 2360, 4606, 8946, 17345, 33579, 64776, 124157, 235847, 443145, 822344, 1505117, 2713796, 4816071, 8409952 }, + new List> + { + new() { 12, 37, 80, 157, 306, 598, 1162, 2246, 4340, 8399, 16234, 31197, 59381, 111690, 207298, 379199, 682773, 1208679, 2102275, 3593881 }, + new() { 25, 43, 77, 149, 292, 564, 1084, 2094, 4059, 7835, 14963, 28184, 52309, 95608, 171901, 303574, 525906, 893596, 1491606 }, + new() { 18, 34, 72, 143, 272, 520, 1010, 1965, 3776, 7128, 13221, 24125, 43299, 76293, 131673, 222332, 367690, 598010 }, + new() { 16, 38, 71, 129, 248, 490, 955, 1811, 3352, 6093, 10904, 19174, 32994, 55380, 90659, 145358, 230320 }, + new() { 22, 33, 58, 119, 242, 465, 856, 1541, 2741, 4811, 8270, 13820, 22386, 35279, 54699, 84962 }, + new() { 11, 25, 61, 123, 223, 391, 685, 1200, 2070, 3459, 5550, 8566, 12893, 19420, 30263 }, + new() { 14, 36, 62, 100, 168, 294, 515, 870, 1389, 2091, 3016, 4327, 6527, 10843 }, + new() { 22, 26, 38, 68, 126, 221, 355, 519, 702, 925, 1311, 2200, 4316 }, + new() { 4, 12, 30, 58, 95, 134, 164, 183, 223, 386, 889, 2116 }, + new() { 8, 18, 28, 37, 39, 30, 19, 40, 163, 503, 1227 }, + new() { 10, 10, 9, 2, -9, -11, 21, 123, 340, 724 }, + new() { 0, -1, -7, -11, -2, 32, 102, 217, 384 }, + new() { -1, -6, -4, 9, 34, 70, 115, 167 }, + new() { -5, 2, 13, 25, 36, 45, 52 }, + new() { 7, 11, 12, 11, 9, 7 }, + new() { 4, 1, -1, -2, -2 }, + new() { -3, -2, -1, 0 }, + new() { 1, 1, 1 }, + new() { 0, 0 }, + } + } }; public static IEnumerable CalculateDifferencesTestData => @@ -71,6 +210,11 @@ public class ValueHistoryTests new List { 10, 13, 16, 21, 30, 45 }, new List { 3, 3, 5, 9, 15 }, }, + new object[] + { + new List { 10, 13, 16 }, + new List { 3, 3 }, + } }; } } \ No newline at end of file diff --git a/09/MirageMaintenance/Program.cs b/09/MirageMaintenance/Program.cs index 3a825bd..18ce111 100644 --- a/09/MirageMaintenance/Program.cs +++ b/09/MirageMaintenance/Program.cs @@ -1,10 +1,35 @@ -namespace MirageMaintenance; +using System.Diagnostics; + +namespace MirageMaintenance; class Program { public static async Task Main(string[] args) { - return await Task.FromResult(0); + 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 input = await File.ReadAllLinesAsync(args[0]); + + var stopwatch = new Stopwatch(); + stopwatch.Start(); + + var result = OasisReport.Parse(input).CalculateSumOfNextValues(); + + stopwatch.Stop(); + + Console.WriteLine($"The sum of all next values is {result}. ({stopwatch.ElapsedMilliseconds}ms)"); + + return (int)result; } } @@ -14,6 +39,10 @@ public class OasisReport( { public List ValueHistories { get; init; } = valueHistories; + public long CalculateSumOfNextValues() => ValueHistories + .Select(valueHistory => valueHistory.CalculateNextValue()) + .Sum(); + public static OasisReport Parse(string[] oasisReportInput) { var valueHistories = new List(); @@ -51,7 +80,7 @@ public class ValueHistory( while ( allHistoricalValues.Count is 0 || - allHistoricalValues.Last().Sum() is not 0 + allHistoricalValues.Last().Any(value => value is not 0) ) { var historicalValues = CalculateDifferences(currentValues); @@ -65,7 +94,23 @@ public class ValueHistory( public long CalculateNextValue() { var historicalValues = CalculateHistory(); - var values = historicalValues.Prepend(Values).ToList(); - return 0; + var values = historicalValues.Prepend(Values).Reverse().ToList(); + + for (var i = 0; i < values.Count; i++) + { + var currentValues = values[i]; + + if (i is 0) + { + currentValues.Add(0); + continue; + } + + var previousValues = values[i - 1]; + + currentValues.Add(currentValues.Last() + previousValues.Last()); + } + + return values.Last().Last(); } } \ No newline at end of file From 160abd3d2ed9d128f0a129af96f8bfbfa4371c82 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Sat, 9 Dec 2023 21:15:42 -0600 Subject: [PATCH 4/8] feat: solve part 2 --- .../ValueHistoryTests.cs | 17 ++++++++++++++++ 09/MirageMaintenance/Program.cs | 20 ++++++++++++++----- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/09/MirageMaintenance.Tests/ValueHistoryTests.cs b/09/MirageMaintenance.Tests/ValueHistoryTests.cs index df7382a..1804854 100644 --- a/09/MirageMaintenance.Tests/ValueHistoryTests.cs +++ b/09/MirageMaintenance.Tests/ValueHistoryTests.cs @@ -23,8 +23,25 @@ public class ValueHistoryTests new ValueHistory(values).CalculateNextValue().Should().Be(expected); } + [Theory] + [MemberData(nameof(TestData.CalculateNextValueTestDataBackwards), MemberType = typeof(TestData))] + public void CalculateNextValue_GivenAListOfValuesAndBackwardsIsTrue_ItShouldReturnTheNextValue(List values, long expected) + { + new ValueHistory(values).CalculateNextValue(true).Should().Be(expected); + } + public static class TestData { + public static IEnumerable CalculateNextValueTestDataBackwards => + new List + { + new object[] + { + new List { 10, 13, 16, 21, 30, 45 }, + 5, + } + }; + public static IEnumerable CalculateNextValueTestData => new List { diff --git a/09/MirageMaintenance/Program.cs b/09/MirageMaintenance/Program.cs index 18ce111..be55374 100644 --- a/09/MirageMaintenance/Program.cs +++ b/09/MirageMaintenance/Program.cs @@ -18,12 +18,13 @@ class Program return -2; } + var isPart2 = args.Length > 1 && args[1] == "part2"; var input = await File.ReadAllLinesAsync(args[0]); var stopwatch = new Stopwatch(); stopwatch.Start(); - var result = OasisReport.Parse(input).CalculateSumOfNextValues(); + var result = OasisReport.Parse(input).CalculateSumOfNextValues(isPart2); stopwatch.Stop(); @@ -39,8 +40,8 @@ public class OasisReport( { public List ValueHistories { get; init; } = valueHistories; - public long CalculateSumOfNextValues() => ValueHistories - .Select(valueHistory => valueHistory.CalculateNextValue()) + public long CalculateSumOfNextValues(bool backwards = false) => ValueHistories + .Select(valueHistory => valueHistory.CalculateNextValue(backwards)) .Sum(); public static OasisReport Parse(string[] oasisReportInput) @@ -91,11 +92,16 @@ public class ValueHistory( return allHistoricalValues; } - public long CalculateNextValue() + public long CalculateNextValue(bool backwards = false) { var historicalValues = CalculateHistory(); var values = historicalValues.Prepend(Values).Reverse().ToList(); + if (backwards) + { + values.ForEach(value => value.Reverse()); + } + for (var i = 0; i < values.Count; i++) { var currentValues = values[i]; @@ -108,7 +114,11 @@ public class ValueHistory( var previousValues = values[i - 1]; - currentValues.Add(currentValues.Last() + previousValues.Last()); + var extrapolatedValue = backwards + ? currentValues.Last() - previousValues.Last() + : currentValues.Last() + previousValues.Last(); + + currentValues.Add(extrapolatedValue); } return values.Last().Last(); From 40b46d7829cb48fc8cce50b7ea175795f58d6776 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Sat, 9 Dec 2023 21:18:25 -0600 Subject: [PATCH 5/8] chore: add xml comments --- 09/MirageMaintenance/Program.cs | 42 ++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/09/MirageMaintenance/Program.cs b/09/MirageMaintenance/Program.cs index be55374..8399a54 100644 --- a/09/MirageMaintenance/Program.cs +++ b/09/MirageMaintenance/Program.cs @@ -2,7 +2,7 @@ namespace MirageMaintenance; -class Program +public class Program { public static async Task Main(string[] args) { @@ -34,16 +34,34 @@ class Program } } +/// +/// Represents a report from the Oasis. +/// +/// The value histories. +/// An instance of . public class OasisReport( List valueHistories ) { + /// + /// Gets the value histories. + /// public List ValueHistories { get; init; } = valueHistories; + /// + /// Calculates the sum of all next values. + /// + /// if set to true will extrapolate next values backwards + /// The sum of all next values. public long CalculateSumOfNextValues(bool backwards = false) => ValueHistories .Select(valueHistory => valueHistory.CalculateNextValue(backwards)) .Sum(); + /// + /// Parses the specified oasis report input. + /// + /// The oasis report input. + /// An instance of . public static OasisReport Parse(string[] oasisReportInput) { var valueHistories = new List(); @@ -63,17 +81,34 @@ public class OasisReport( } } +/// +/// Represents a value history. +/// +/// The values. +/// An instance of . public class ValueHistory( List values ) { + /// + /// Gets the values. + /// List Values { get; init; } = values; + /// + /// Calculates the differences between each value. + /// + /// The values. + /// The differences between each value. public List CalculateDifferences(List values) => Enumerable .Range(0, values.Count - 1) .Select(i => values[i + 1] - values[i]) .ToList(); + /// + /// Calculates the history. + /// + /// The history. public List> CalculateHistory() { var allHistoricalValues = new List>(); @@ -92,6 +127,11 @@ public class ValueHistory( return allHistoricalValues; } + /// + /// Calculates the next value. + /// + /// if set to true will extrapolate next value backwards + /// The next value. public long CalculateNextValue(bool backwards = false) { var historicalValues = CalculateHistory(); From 98fbebc21bc91f273e76c62b43d77f40c424dc6a Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Sat, 9 Dec 2023 21:19:05 -0600 Subject: [PATCH 6/8] chore: dotnet format --- 07/CamelCards.Tests/GlobalUsings.cs | 2 +- 08/HauntedWasteland.Tests/GlobalUsings.cs | 3 ++- 09/MirageMaintenance.Tests/GlobalUsings.cs | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/07/CamelCards.Tests/GlobalUsings.cs b/07/CamelCards.Tests/GlobalUsings.cs index 2d5b473..d6f0167 100644 --- a/07/CamelCards.Tests/GlobalUsings.cs +++ b/07/CamelCards.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/08/HauntedWasteland.Tests/GlobalUsings.cs b/08/HauntedWasteland.Tests/GlobalUsings.cs index 7fef4b0..2d5b473 100644 --- a/08/HauntedWasteland.Tests/GlobalUsings.cs +++ b/08/HauntedWasteland.Tests/GlobalUsings.cs @@ -1,2 +1,3 @@ +global using FluentAssertions; + global using Xunit; -global using FluentAssertions; \ No newline at end of file diff --git a/09/MirageMaintenance.Tests/GlobalUsings.cs b/09/MirageMaintenance.Tests/GlobalUsings.cs index 7fef4b0..2d5b473 100644 --- a/09/MirageMaintenance.Tests/GlobalUsings.cs +++ b/09/MirageMaintenance.Tests/GlobalUsings.cs @@ -1,2 +1,3 @@ +global using FluentAssertions; + global using Xunit; -global using FluentAssertions; \ No newline at end of file From 225828583d4d86b1ea0402e829509f1d8a409f0e Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Sat, 9 Dec 2023 21:21:12 -0600 Subject: [PATCH 7/8] docs: update README.md --- README.md | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 8fb3106..df65687 100644 --- a/README.md +++ b/README.md @@ -42,30 +42,30 @@ dotnet build ## Challenges -| Day | Problem | Solution | Status | Notes | -| --- | -------------------------- | :--------------------------------: | :----: | ------------------------------------------------------------------------------------------------------- | -| 01 | [Problem](./01/PROBLEM.md) | [Solution](./01/Trebuchet/) | ✅ | The trickiest part here was accounting for overlapping digit words. | -| 02 | [Problem](./02/PROBLEM.md) | [Solution](./02/CubeConundrum/) | ✅ | The key to me here was to parse the input into a useful model. | -| 03 | [Problem](./03/PROBLEM.md) | [Solution](./03/GearRatios/) | ✅ | The edge case that got me here was lines ending with a part number. | -| 04 | [Problem](./04/PROBLEM.md) | [Solution](./04/Scratchcards/) | ✅ | Part 2 gets out of hand quickly with just 200 cards. | -| 05 | [Problem](./05/PROBLEM.md) | [Solution](./05/IYGASAF/) | ✅ | I brute forced part 2 using parallelism. I know shame. | -| 06 | [Problem](./06/PROBLEM.md) | [Solution](./06/WaitForIt/) | ✅ | Thank goodness part 2 was not like 5's part 2. 😅 | -| 07 | [Problem](./07/PROBLEM.md) | [Solution](./07/CamelCards/) | ✅ | What took me longest here was I missed a case when jokers are wild and there are three groups of cards. | -| 08 | [Problem](./08/PROBLEM.md) | [Solution](./08/HauntedWasteland/) | ✅ | Got to implement a least common multiple algorithm for part 2. | -| 09 | [Problem](./09/PROBLEM.md) | [Solution](./09/) | ⌛ | -| 10 | [Problem](./10/PROBLEM.md) | [Solution](./10/) | ⌛ | -| 11 | [Problem](./11/PROBLEM.md) | [Solution](./11/) | ⌛ | -| 12 | [Problem](./12/PROBLEM.md) | [Solution](./12/) | ⌛ | -| 13 | [Problem](./13/PROBLEM.md) | [Solution](./13/) | ⌛ | -| 14 | [Problem](./14/PROBLEM.md) | [Solution](./14/) | ⌛ | -| 15 | [Problem](./15/PROBLEM.md) | [Solution](./15/) | ⌛ | -| 16 | [Problem](./16/PROBLEM.md) | [Solution](./16/) | ⌛ | -| 17 | [Problem](./17/PROBLEM.md) | [Solution](./17/) | ⌛ | -| 18 | [Problem](./18/PROBLEM.md) | [Solution](./18/) | ⌛ | -| 19 | [Problem](./19/PROBLEM.md) | [Solution](./19/) | ⌛ | -| 20 | [Problem](./20/PROBLEM.md) | [Solution](./20/) | ⌛ | -| 21 | [Problem](./21/PROBLEM.md) | [Solution](./21/) | ⌛ | -| 22 | [Problem](./22/PROBLEM.md) | [Solution](./22/) | ⌛ | -| 23 | [Problem](./23/PROBLEM.md) | [Solution](./23/) | ⌛ | -| 24 | [Problem](./24/PROBLEM.md) | [Solution](./24/) | ⌛ | -| 25 | [Problem](./25/PROBLEM.md) | [Solution](./25/) | ⌛ | +| Day | Problem | Solution | Status | Notes | +| --- | -------------------------- | :---------------------------------: | :----: | ------------------------------------------------------------------------------------------------------------------------------------ | +| 01 | [Problem](./01/PROBLEM.md) | [Solution](./01/Trebuchet/) | ✅ | The trickiest part here was accounting for overlapping digit words. | +| 02 | [Problem](./02/PROBLEM.md) | [Solution](./02/CubeConundrum/) | ✅ | The key to me here was to parse the input into a useful model. | +| 03 | [Problem](./03/PROBLEM.md) | [Solution](./03/GearRatios/) | ✅ | The edge case that got me here was lines ending with a part number. | +| 04 | [Problem](./04/PROBLEM.md) | [Solution](./04/Scratchcards/) | ✅ | Part 2 gets out of hand quickly with just 200 cards. | +| 05 | [Problem](./05/PROBLEM.md) | [Solution](./05/IYGASAF/) | ✅ | I brute forced part 2 using parallelism. I know shame. | +| 06 | [Problem](./06/PROBLEM.md) | [Solution](./06/WaitForIt/) | ✅ | Thank goodness part 2 was not like 5's part 2. 😅 | +| 07 | [Problem](./07/PROBLEM.md) | [Solution](./07/CamelCards/) | ✅ | What took me longest here was I missed a case when jokers are wild and there are three groups of cards. | +| 08 | [Problem](./08/PROBLEM.md) | [Solution](./08/HauntedWasteland/) | ✅ | Got to implement a least common multiple algorithm for part 2. | +| 09 | [Problem](./09/PROBLEM.md) | [Solution](./09/MirageMaintenance/) | ✅ | Part 1 took me unnecessarily long. The bug was summing a line to check for all zeros is bad idea when negative numbers are involved. | +| 10 | [Problem](./10/PROBLEM.md) | [Solution](./10/) | ⌛ | +| 11 | [Problem](./11/PROBLEM.md) | [Solution](./11/) | ⌛ | +| 12 | [Problem](./12/PROBLEM.md) | [Solution](./12/) | ⌛ | +| 13 | [Problem](./13/PROBLEM.md) | [Solution](./13/) | ⌛ | +| 14 | [Problem](./14/PROBLEM.md) | [Solution](./14/) | ⌛ | +| 15 | [Problem](./15/PROBLEM.md) | [Solution](./15/) | ⌛ | +| 16 | [Problem](./16/PROBLEM.md) | [Solution](./16/) | ⌛ | +| 17 | [Problem](./17/PROBLEM.md) | [Solution](./17/) | ⌛ | +| 18 | [Problem](./18/PROBLEM.md) | [Solution](./18/) | ⌛ | +| 19 | [Problem](./19/PROBLEM.md) | [Solution](./19/) | ⌛ | +| 20 | [Problem](./20/PROBLEM.md) | [Solution](./20/) | ⌛ | +| 21 | [Problem](./21/PROBLEM.md) | [Solution](./21/) | ⌛ | +| 22 | [Problem](./22/PROBLEM.md) | [Solution](./22/) | ⌛ | +| 23 | [Problem](./23/PROBLEM.md) | [Solution](./23/) | ⌛ | +| 24 | [Problem](./24/PROBLEM.md) | [Solution](./24/) | ⌛ | +| 25 | [Problem](./25/PROBLEM.md) | [Solution](./25/) | ⌛ | From ca475082bbf8b1758a384d70403427715a95c257 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Sat, 9 Dec 2023 21:25:43 -0600 Subject: [PATCH 8/8] tests: add tests for actual puzzle input --- .../OasisReportTests.cs | 33 +++++++++++++++++-- .../ValueHistoryTests.cs | 20 ++++++++--- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/09/MirageMaintenance.Tests/OasisReportTests.cs b/09/MirageMaintenance.Tests/OasisReportTests.cs index d3ffdb3..c69fc91 100644 --- a/09/MirageMaintenance.Tests/OasisReportTests.cs +++ b/09/MirageMaintenance.Tests/OasisReportTests.cs @@ -6,7 +6,10 @@ public class UnitTest1 [MemberData(nameof(TestData.OasisReportParseTestData), MemberType = typeof(TestData))] public void Parse_GivenAReportInput_ItShouldReturnExpectedOasisReportInstance(string[] input, OasisReport expected) { - OasisReport.Parse(input).Should().BeEquivalentTo(expected); + OasisReport + .Parse(input) + .Should() + .BeEquivalentTo(expected); } [Fact] @@ -19,11 +22,37 @@ public class UnitTest1 "10 13 16 21 30 45", }; - OasisReport.Parse(input).CalculateSumOfNextValues().Should().Be(114); + OasisReport + .Parse(input) + .CalculateSumOfNextValues() + .Should() + .Be(114); + } + + [Fact] + public void CalculateSumOfNextValues_WhenGivenInput_ItShouldReturnTheSumOfAllNextValues() + { + OasisReport + .Parse(TestData.Input) + .CalculateSumOfNextValues() + .Should() + .Be(2175229206); + } + + [Fact] + public void CalculateSumOfNextValues_WhenGivenInputAndBackwardsIsTrue_ItShouldReturnTheSumOfAllNextValues() + { + OasisReport + .Parse(TestData.Input) + .CalculateSumOfNextValues(true) + .Should() + .Be(942); } public static class TestData { + public static readonly string[] Input = File.ReadAllLines("INPUT.txt"); + public static IEnumerable OasisReportParseTestData => new List { diff --git a/09/MirageMaintenance.Tests/ValueHistoryTests.cs b/09/MirageMaintenance.Tests/ValueHistoryTests.cs index 1804854..828ae2e 100644 --- a/09/MirageMaintenance.Tests/ValueHistoryTests.cs +++ b/09/MirageMaintenance.Tests/ValueHistoryTests.cs @@ -6,28 +6,40 @@ public class ValueHistoryTests [MemberData(nameof(TestData.CalculateDifferencesTestData), MemberType = typeof(TestData))] public void CalculateDifferences_GivenAListOfValues_ItShouldReturnAListOfDifferences(List values, List expected) { - new ValueHistory([]).CalculateDifferences(values).Should().BeEquivalentTo(expected); + new ValueHistory([]) + .CalculateDifferences(values) + .Should() + .BeEquivalentTo(expected); } [Theory] [MemberData(nameof(TestData.CalculateHistoryTestData), MemberType = typeof(TestData))] public void CalculateHistory_GivenAListOfValues_ItShouldReturnAListOfHistoricalValues(List values, List> expected) { - new ValueHistory(values).CalculateHistory().Should().BeEquivalentTo(expected); + new ValueHistory(values) + .CalculateHistory() + .Should() + .BeEquivalentTo(expected); } [Theory] [MemberData(nameof(TestData.CalculateNextValueTestData), MemberType = typeof(TestData))] public void CalculateNextValue_GivenAListOfValues_ItShouldReturnTheNextValue(List values, long expected) { - new ValueHistory(values).CalculateNextValue().Should().Be(expected); + new ValueHistory(values) + .CalculateNextValue() + .Should() + .Be(expected); } [Theory] [MemberData(nameof(TestData.CalculateNextValueTestDataBackwards), MemberType = typeof(TestData))] public void CalculateNextValue_GivenAListOfValuesAndBackwardsIsTrue_ItShouldReturnTheNextValue(List values, long expected) { - new ValueHistory(values).CalculateNextValue(true).Should().Be(expected); + new ValueHistory(values) + .CalculateNextValue(true) + .Should() + .Be(expected); } public static class TestData