From 2858fc14e9a4b6b35bae47cf37ea09c2a46562fd Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Thu, 20 Nov 2025 09:04:39 -0600 Subject: [PATCH] feat: wip on solution --- 15/LensLibrary.Tests/LaunchSequenceTests.cs | 51 +++++++++++ 15/LensLibrary.Tests/LensLibrary.Tests.csproj | 6 ++ 15/LensLibrary.Tests/UnitTest1.cs | 10 --- 15/LensLibrary/Program.cs | 90 +++++++++++++++---- 4 files changed, 130 insertions(+), 27 deletions(-) create mode 100644 15/LensLibrary.Tests/LaunchSequenceTests.cs delete mode 100644 15/LensLibrary.Tests/UnitTest1.cs diff --git a/15/LensLibrary.Tests/LaunchSequenceTests.cs b/15/LensLibrary.Tests/LaunchSequenceTests.cs new file mode 100644 index 0000000..3087eb2 --- /dev/null +++ b/15/LensLibrary.Tests/LaunchSequenceTests.cs @@ -0,0 +1,51 @@ +namespace LensLibrary.Tests; + +public class LaunchSequenceTests +{ + [Theory] + [MemberData(nameof(TestData.InitializeTestData), MemberType = typeof(TestData))] + public void Initialize_WhenCalled_ItShouldReturnFocusPowerOfLensConfiguration(LaunchSequence sequence, long expected) + { + var result = sequence.Initialize(); + result.Should().Be(expected); + } + + [Fact] + public void Initialize_WhenCalledOnInputLaunchSequence_ItShouldReturnFocusPowerOfLensConfiguration() + { + var input = File.ReadAllText("INPUT.txt"); + var sequence = LaunchSequence.Parse(input, true); + var result = sequence.Initialize(); + result.Should().BeGreaterThan(244789); + } + + + public static class TestData + { + public static readonly LaunchSequence TestSequence = new( + [ + new Step("rn", Operation.Insertion, 1), + new Step("cm", Operation.Removal, null), + new Step("qp", Operation.Insertion, 3), + new Step("cm", Operation.Insertion, 2), + new Step("qp", Operation.Removal, null), + new Step("pc", Operation.Insertion, 4), + new Step("ot", Operation.Insertion, 9), + new Step("ab", Operation.Insertion, 5), + new Step("pc", Operation.Removal, null), + new Step("pc", Operation.Insertion, 6), + new Step("ot", Operation.Insertion, 7), + ] + ); + + public static IEnumerable InitializeTestData => + new List + { + new object[] + { + TestSequence, + 145, + } + }; + } +} \ No newline at end of file diff --git a/15/LensLibrary.Tests/LensLibrary.Tests.csproj b/15/LensLibrary.Tests/LensLibrary.Tests.csproj index f7dbfc1..690f77f 100644 --- a/15/LensLibrary.Tests/LensLibrary.Tests.csproj +++ b/15/LensLibrary.Tests/LensLibrary.Tests.csproj @@ -27,4 +27,10 @@ + + + PreserveNewest + + + diff --git a/15/LensLibrary.Tests/UnitTest1.cs b/15/LensLibrary.Tests/UnitTest1.cs deleted file mode 100644 index 41e3234..0000000 --- a/15/LensLibrary.Tests/UnitTest1.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace LensLibrary.Tests; - -public class UnitTest1 -{ - [Fact] - public void Test1() - { - - } -} \ No newline at end of file diff --git a/15/LensLibrary/Program.cs b/15/LensLibrary/Program.cs index 74880e6..3387695 100644 --- a/15/LensLibrary/Program.cs +++ b/15/LensLibrary/Program.cs @@ -18,21 +18,30 @@ public class Program return -2; } + var isPart2 = args.Length > 1 && args[1] == "part2"; var input = await File.ReadAllTextAsync(args[0]); var stopwatch = new Stopwatch(); stopwatch.Start(); - var result = LaunchSequence - .Parse(input) - .Steps - .Sum(step => step.HashLabel()); + + var sequence = LaunchSequence.Parse(input, isPart2); + var result = isPart2 + ? sequence.Initialize() + : sequence.Steps.Sum(step => step.LabelHash); stopwatch.Stop(); - Console.WriteLine($"The total is {result}. ({stopwatch.ElapsedMilliseconds}ms)"); + if (isPart2) + { + Console.WriteLine($"The focusing power is {result}. ({stopwatch.ElapsedMilliseconds}ms)"); + } + else + { + Console.WriteLine($"The total is {result}. ({stopwatch.ElapsedMilliseconds}ms)"); + } - return result; + return (int)result; } } @@ -44,6 +53,9 @@ public class LaunchSequence( public long Initialize() { + // each box is numbered + // each box can contain lenses + // a lense has a label and a focal length var boxes = new Dictionary>(); foreach (var num in Enumerable.Range(0, 255)) @@ -51,7 +63,53 @@ public class LaunchSequence( boxes.Add(num, []); } - return 0; + foreach (var step in Steps) + { + var box = boxes[step.LabelHash]; + + switch (step.Operation) + { + case Operation.Removal: + { + box.Remove(step.Label); + break; + } + case Operation.Insertion: + { + if (step.LensFocalLength.HasValue) + { + if (box.ContainsKey(step.Label)) + { + box[step.Label] = step.LensFocalLength.Value; + } + else + { + box.Add(step.Label, step.LensFocalLength.Value); + } + } + break; + } + default: + throw new ArgumentException("Invalid operation.", nameof(step.Operation)); + } + } + + var total = 0L; + + foreach (var box in boxes) + { + var boxNumber = box.Key + 1; + var lenses = box.Value; + + for (var i = 0; i < lenses.Count; i++) + { + var lensNumber = i + 1; + var focalLength = box.Value.ElementAt(i).Value; + total += boxNumber * lensNumber * focalLength; + } + } + + return total; } public static LaunchSequence Parse(string input, bool part2 = false) @@ -77,16 +135,14 @@ public class Step( public string Label { get; init; } = label; public Operation Operation { get; init; } = operation; public int? LensFocalLength { get; init; } = lensFocalLength; - - public int HashLabel() => Label - .Aggregate(0, (hash, character) => - { - var ascii = (int)character; - hash += ascii; - hash *= 17; - hash %= 256; - return hash; - }); + public int LabelHash => Label.Aggregate(0, (hash, character) => + { + var ascii = (int)character; + hash += ascii; + hash *= 17; + hash %= 256; + return hash; + }); public static Step Parse(string input, bool part2 = false) {