-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
130 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace AdventOfCode.Year2023.Day15; | ||
|
||
internal enum InitializationOperationType | ||
{ | ||
None = 0, | ||
Remove, | ||
Insert, | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace AdventOfCode.Year2023.Day15; | ||
|
||
internal readonly struct InitializationStep(string label, InitializationOperationType operation, int parameter = default) | ||
{ | ||
public string Label { get; } = label; | ||
public InitializationOperationType Operation { get; } = operation; | ||
public int Parameter { get; } = parameter; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,50 +1,51 @@ | ||
using AdventOfCode.Common.SpanExtensions; | ||
using AdventOfCode.Common.SpanExtensions; | ||
|
||
namespace AdventOfCode.Year2023.Day15; | ||
|
||
internal static class InputReader | ||
internal sealed class InputReader(Day15SolverOptions options) | ||
{ | ||
public static List<string> ReadInitializationSequence(string input) | ||
private readonly char _sequenceSeparator = options.SequenceSeparator; | ||
private readonly char _removeOperationChar = options.RemoveOperationChar; | ||
private readonly char _insertOperationChar = options.InsertOperationChar; | ||
|
||
|
||
public List<string> ReadInitializationSequence(string input) | ||
{ | ||
var sequence = new List<string>(input.AsSpan().Count(',') + 1); | ||
foreach (var sequenceSpan in input.AsSpan().Trim().Split(',')) | ||
var sequence = new List<string>(input.AsSpan().Count(_sequenceSeparator) + 1); | ||
foreach (var sequenceSpan in input.AsSpan().Trim().Split(_sequenceSeparator)) | ||
{ | ||
sequence.Add(sequenceSpan.Trim().ToString()); | ||
} | ||
|
||
return sequence; | ||
} | ||
} | ||
|
||
internal readonly struct InitializationStep(string label, InitializationOperationType operation, int parameter = default) | ||
{ | ||
public string Label { get; } = label; | ||
public InitializationOperationType Operation { get; } = operation; | ||
public int Parameter { get; } = parameter; | ||
|
||
public static InitializationStep Parse(string line) => Parse(line.AsSpan()); | ||
public InitializationStep ParseStep(string line) => ParseStep(line.AsSpan()); | ||
|
||
public static InitializationStep Parse(ReadOnlySpan<char> line) | ||
public InitializationStep ParseStep(ReadOnlySpan<char> line) | ||
{ | ||
line = line.Trim(); | ||
int operationCharIndex = line.LastIndexOfAny('-', '='); | ||
InitializationOperationType operation = line[operationCharIndex] switch | ||
{ | ||
'-' => InitializationOperationType.Remove, | ||
'=' => InitializationOperationType.Insert, | ||
_ => throw new InvalidOperationException("Invalid operation character.") | ||
}; | ||
int operationCharIndex = line.LastIndexOfAny(_removeOperationChar, '='); | ||
InitializationOperationType operation = ParseOperation(line[operationCharIndex]); | ||
var labelSpan = line[..operationCharIndex]; | ||
string label = labelSpan.ToString(); | ||
var parameterSpan = line[(operationCharIndex + 1)..]; | ||
int parameter = parameterSpan.IsEmpty ? default : int.Parse(parameterSpan); | ||
return new(label, operation, parameter); | ||
} | ||
} | ||
|
||
internal enum InitializationOperationType | ||
{ | ||
None, | ||
Remove, | ||
Insert, | ||
private InitializationOperationType ParseOperation(char operationChar) | ||
{ | ||
if (operationChar == _removeOperationChar) | ||
{ | ||
return InitializationOperationType.Remove; | ||
} | ||
|
||
if (operationChar == _insertOperationChar) | ||
{ | ||
return InitializationOperationType.Insert; | ||
} | ||
|
||
throw new InvalidOperationException("Invalid operation character."); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
namespace AdventOfCode.Year2023.Day15; | ||
|
||
internal sealed class LensConfigurator | ||
{ | ||
private readonly List<Lens>?[] _boxes = new List<Lens>?[256]; | ||
|
||
private List<Lens> GetBox(int boxNumber) | ||
{ | ||
var box = _boxes[boxNumber]; | ||
if (box is null) | ||
{ | ||
box = new(1); | ||
_boxes[boxNumber] = box; | ||
} | ||
|
||
return box; | ||
} | ||
|
||
public void PerformStep(InitializationStep step) | ||
{ | ||
int labelHash = HolidayAsciiStringHelper.Hash(step.Label); | ||
var box = GetBox(labelHash); | ||
|
||
switch (step.Operation) | ||
{ | ||
case InitializationOperationType.Remove: | ||
box.RemoveAll(lens => lens.Label == step.Label); | ||
break; | ||
case InitializationOperationType.Insert: | ||
{ | ||
var lens = box.Find(l => l.Label == step.Label); | ||
if (lens is null) | ||
{ | ||
lens = new(step.Label); | ||
box.Add(lens); | ||
} | ||
|
||
lens.FocalLength = step.Parameter; | ||
break; | ||
} | ||
default: | ||
throw new InvalidOperationException($"Invalid operation to perform: {step.Operation}."); | ||
} | ||
} | ||
|
||
public int CalculateFocusingPower() | ||
{ | ||
int totalFocusingPower = 0; | ||
for (int boxNumber = 0; boxNumber < _boxes.Length; boxNumber++) | ||
{ | ||
var box = _boxes[boxNumber]; | ||
if (box is null) continue; | ||
for (int slotNumber = 0; slotNumber < box.Count; slotNumber++) | ||
{ | ||
var lens = box[slotNumber]; | ||
totalFocusingPower += CalculateSingleLensFocusingPower(boxNumber, slotNumber, lens); | ||
} | ||
} | ||
|
||
return totalFocusingPower; | ||
} | ||
|
||
private static int CalculateSingleLensFocusingPower(int boxNumber, int slotNumber, Lens lens) | ||
{ | ||
return (boxNumber + 1) * (slotNumber + 1) * lens.FocalLength; | ||
} | ||
|
||
private sealed class Lens(string label) | ||
{ | ||
public string Label { get; } = label; | ||
public int FocalLength { get; set; } | ||
} | ||
} |