Skip to content

Commit

Permalink
2023-15 part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
tetsuo13 committed Jan 17, 2024
1 parent cb940b2 commit bbb88cd
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 13 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ AdventOfCode --year 2023 --day 1
| [Wait For It](https://adventofcode.com/2023/day/6) | [Solution](./src/AdventOfCode/Calendar/2023/Day06/Solution.cs) | 2023-06 | Completed |
| [Haunted Wasteland](https://adventofcode.com/2023/day/8) | [Solution](./src/AdventOfCode/Calendar/2023/Day08/Solution.cs) | 2023-08 | Completed |
| [Mirage Maintenance](https://adventofcode.com/2023/day/9) | [Solution](./src/AdventOfCode/Calendar/2023/Day09/Solution.cs) | 2023-09 | Completed |
| [Lens Library](https://adventofcode.com/2023/day/15) | [Solution](./src/AdventOfCode/Calendar/2023/Day15/Solution.cs) | 2023-15 | Part 1 |
| [Lens Library](https://adventofcode.com/2023/day/15) | [Solution](./src/AdventOfCode/Calendar/2023/Day15/Solution.cs) | 2023-15 | Completed |
67 changes: 65 additions & 2 deletions src/AdventOfCode/Calendar/2023/Day15/Solution.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace AdventOfCode.Calendar._2023.Day15;
using System.Collections.Specialized;

namespace AdventOfCode.Calendar._2023.Day15;

public class Solution : BaseSolution
{
Expand All @@ -9,11 +11,72 @@ public override async Task<object> Run(RunMode runMode)

return runMode switch
{
RunMode.PartOne => SumHashSteps(steps),
RunMode.PartOne => SumHashSteps(steps), // Elegant
RunMode.PartTwo => TotalFocusingPower(steps), // Not as much
_ => throw new ArgumentOutOfRangeException(nameof(runMode))
};
}

private static int TotalFocusingPower(string[] steps)
{
// It's ordered dictionaries all the way down...
// There's opportunity to use/create a better collection type --
// something that provides generic support, access by both index and
// key, and maintains order in which values were inserted.

// 256 boxes of lens slots.
var boxes = new OrderedDictionary(256);

// The Holiday ASCII String Helper Manual Arrangement Procedure.
foreach (var step in steps)
{
var label = new string(step.TakeWhile(char.IsLetter).ToArray());

// Use string hash so that we're accessing OrderedDictionary by
// key instead of index.
var hash = CalculateHashAlgorithm(label).ToString();

// The next character after the label indicates one of two possible
// operations.
switch (step[label.Length])
{
case '-':
if (boxes.Contains(hash))
{
((OrderedDictionary)boxes[hash]!).Remove(label);
}
break;

case '=':
if (!boxes.Contains(hash))
{
boxes.Add(hash, new OrderedDictionary());
}

var lenses = (OrderedDictionary)boxes[hash]!;
lenses[label] = Convert.ToInt32(step[(label.Length + 1)..]);
break;

default:
throw new NotSupportedException($"Unrecognized operator in step '{step}'");
}
}

var sum = 0;

foreach (string boxIndex in boxes.Keys)
{
var box = (OrderedDictionary)boxes[boxIndex]!;

for (int slot = 0; slot < box.Count; slot++)
{
sum += (Convert.ToInt32(boxIndex) + 1) * (slot + 1) * (int)box[slot]!;
}
}

return sum;
}

private static int SumHashSteps(string[] steps) =>
steps.Select(CalculateHashAlgorithm).Sum();

Expand Down
10 changes: 4 additions & 6 deletions src/AdventOfCode/Calendar/BaseSolution.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,13 @@ public abstract class BaseSolution
public abstract Task<object> Run(RunMode runMode);

/// <summary>
/// <para>
/// Input file will reside in a subdirectory of the executable. That
/// path will follow the same as the namespace mostly.
/// </para>
/// <para>
/// Using <see langword="virtual"/> keyword so unit tests can replace
/// the method to mock the return.
/// </para>
/// </summary>
/// <remarks>
/// Using <see langword="virtual"/> keyword so unit tests can mock the
/// method without having to resort to reading files.
/// </remarks>
public virtual async Task<string[]> ReadInput()
{
var solutionDirectory = GetType().Namespace!
Expand Down
9 changes: 5 additions & 4 deletions tests/AdventOfCode.Tests/Calendar/2023/Day15/SolutionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ namespace AdventOfCode.Tests.Calendar._2023.Day15;
public class SolutionTests
{
[Theory]
[InlineData("HASH", 52)]
[InlineData("rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7", 1320)]
public async Task Example(string s, int expected)
[InlineData("HASH", RunMode.PartOne, 52)]
[InlineData("rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7", RunMode.PartOne, 1320)]
[InlineData("rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7", RunMode.PartTwo, 145)]
public async Task Example(string s, RunMode runMode, int expected)
{
string[] input = [s];

var solution = new SolutionTestWrapper<Solution>(input);
Assert.Equal(expected, await solution.Run(RunMode.PartOne));
Assert.Equal(expected, await solution.Run(runMode));
}
}

0 comments on commit bbb88cd

Please sign in to comment.