DEV Community

Grant Riordan
Grant Riordan

Posted on

Advent of Code 2023: Day 15 Lens Library

Day 15 : Lens

link to challenge

Overview

Today’s challenge Part1 was pretty straightforward. Simply apply some arithmetic to each character in a string and then Sum() them all up.

Part 2 was a little more complex in that you were requested to maintain lenses using the hashed values and 255 boxes.

Reading Input

The program reads a comma-separated string from the file and splits it into an array of strings using the Split method. The StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries ensure that empty entries and leading/trailing whitespaces are removed.

var inputs = File.ReadAllText("input.txt").Split(',');
Enter fullscreen mode Exit fullscreen mode

Hashing Algorithm

The Hash function processes each string and applies a HASH algorithm to calculate a numeric value. This value is then used to determine the position of the lens in the box (par2).

int Hash(string str)
{
  int currentValue = 0;
  foreach (char c in str)
  {
    currentValue += (int)c;
    currentValue *= 17;
    currentValue %= 256;
  }
  return currentValue;
}
Enter fullscreen mode Exit fullscreen mode

Part 1 Calculation

The program iterates over the input strings, applies the HASH algorithm, and accumulates the results to get the part1 value. The result is then displayed.

int part1 = 0;
foreach (string input in inputs)
{
  part1 += Hash(input);
}
Console.WriteLine($"Solution 1: {part1}");
Enter fullscreen mode Exit fullscreen mode

Part 2: Lens Organization in Boxes

The second part tackles the organization of lenses into boxes based on a sequence of operations specified in the input.

Initializing Boxes and Focal Lengths

Boxes are represented using a list of lists (List<List<string>>), and focal lengths are stored in a dictionary (Dictionary<string, int>). The code uses LINQ to initialize the boxes, ie create 255 entries in the list all with empty lists as their values. Check out my series on Linq if you’re not familiar.

List<List<string>> boxes = Enumerable.Range(0, 256)
   .Select(_ => new List<string>())
   .ToList();
Dictionary<string, int> focalLengths = new Dictionary<string, int>();
Enter fullscreen mode Exit fullscreen mode

Processing Steps

The program iterates over the input steps, which consist of lens-related operations ('=' for adding a lens and '-' for removing a lens).

foreach (string step in inputs)
{
  // Processing code for adding or removing lenses
}
Enter fullscreen mode Exit fullscreen mode

Adding Lenses

For steps with '=', the code splits the input to get the label and focal length. It then calculates the box index using the HASH algorithm. If the box already contains the label, it updates the existing lens, otherwise, it adds a new lens.

if (step.Contains('='))
{
  string[] parts = step.Split('=');
  string label = parts[0];
  int focalLength = int.Parse(parts[1]);
  int box = Hash(label);
  focalLengths[label] = focalLength;

  if (boxes[box].Contains(label))
  {
    int labelIndex = boxes[box].IndexOf(label);
    boxes[box][labelIndex] = label;
  }
  else
  {
    boxes[box].Add(label);
  }
}
Enter fullscreen mode Exit fullscreen mode

Removing Lenses

For steps with '-', the code removes the specified lens from the box.

if (step.Contains('-'))
{
  string label = step[..^1];
  int box = Hash(label);
  boxes[box].Remove(label);
}
Enter fullscreen mode Exit fullscreen mode

Solution 2 Calculation

The final solution involves calculating a score based on the box, slot, and focal length. LINQ is used to achieve this concise calculation.

var solution2 = boxes.SelectMany((box, boxIndex) =>
                box.Select((label, slotIndex) =>
                    (boxIndex + 1) * (slotIndex + 1) * focalLengths[label]))
                    .Sum();
Console.WriteLine($"Solution 2: {solution2}");
Enter fullscreen mode Exit fullscreen mode

There you have it Day 15 complete. As always drop me a follow for further articles / and discussions. Or check out my twitter.

Top comments (0)