Advent of Code 2023: Day 15 Lens Library
Tags: adventofcode, csharp
Published: 2024-01-07 01:06:18

Day 15 : Lens 

[link to challenge](https://adventofcode.com/2023/day/15)

## 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.

```csharp
var inputs = File.ReadAllText("input.txt").Split(',');
```

### 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).

```csharp
int Hash(string str)
{
  int currentValue = 0;
  foreach (char c in str)
  {
    currentValue += (int)c;
    currentValue *= 17;
    currentValue %= 256;
  }
  return currentValue;
}
```

### 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.

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

## 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. 

```csharp
List<List<string>> boxes = Enumerable.Range(0, 256)
   .Select(_ => new List<string>())
   .ToList();
Dictionary<string, int> focalLengths = new Dictionary<string, int>();
```

### Processing Steps

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

```csharp
foreach (string step in inputs)
{
  // Processing code for adding or removing lenses
}
```

### 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.

```csharp
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);
  }
}
```

### Removing Lenses

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

```csharp
if (step.Contains('-'))
{
  string label = step[..^1];
  int box = Hash(label);
  boxes[box].Remove(label);
}
```

### 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.

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

There you have it Day 15 complete. As always drop me a follow for further articles / and discussions. Or check out my [twitter](https://twitter.com/gweaths).