[2k25] Add day 6
This commit is contained in:
209
Days/Day6.cs
Normal file
209
Days/Day6.cs
Normal file
@@ -0,0 +1,209 @@
|
||||
using System.Buffers;
|
||||
using System.Numerics;
|
||||
using Spectre.Console;
|
||||
|
||||
namespace AdventOfCode.Days;
|
||||
|
||||
public class Day6 : Day
|
||||
{
|
||||
public override int Number => 6;
|
||||
public override string Name => "Trash Compactor";
|
||||
|
||||
private static SearchValues<char> DigitsSearchValue = SearchValues.Create(
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
|
||||
);
|
||||
|
||||
public override void RunPart1(bool display = true)
|
||||
{
|
||||
long grandTotal = 0;
|
||||
var numberRows = new List<List<long>>(4);
|
||||
var symbolRow = new List<char>();
|
||||
|
||||
var rowIndex = 0;
|
||||
foreach (var line in Input.EnumerateLines())
|
||||
{
|
||||
if (rowIndex <= 3)
|
||||
{
|
||||
numberRows.Add([]);
|
||||
}
|
||||
|
||||
foreach (var range in line.Split(' '))
|
||||
{
|
||||
var span = line[range];
|
||||
|
||||
// Ignore split columns
|
||||
if (span.IsWhiteSpace())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Numbers
|
||||
if (rowIndex <= 3)
|
||||
{
|
||||
numberRows[rowIndex].Add(int.Parse(span));
|
||||
}
|
||||
// Symbols
|
||||
else
|
||||
{
|
||||
symbolRow.Add(span.Trim()[0]);
|
||||
}
|
||||
}
|
||||
|
||||
rowIndex++;
|
||||
}
|
||||
|
||||
// Do the calculations
|
||||
var count = numberRows[0].Count;
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
checked
|
||||
{
|
||||
grandTotal += symbolRow[i] switch
|
||||
{
|
||||
'+' => numberRows[0][i] + numberRows[1][i] + numberRows[2][i] + numberRows[3][i],
|
||||
'*' => numberRows[0][i] * numberRows[1][i] * numberRows[2][i] * numberRows[3][i],
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (display)
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[green]The grand total is: [yellow]{grandTotal}[/][/]");
|
||||
}
|
||||
}
|
||||
|
||||
public override void RunPart2(bool display = true)
|
||||
{
|
||||
long grandTotal = 0L;
|
||||
var numberRows = new List<List<long>>(4);
|
||||
var symbolRow = new List<char>();
|
||||
|
||||
var lines = Input.Split(Environment.NewLine);
|
||||
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
numberRows.Add([]);
|
||||
}
|
||||
|
||||
var offset = 0;
|
||||
while (offset < lines[0].Length)
|
||||
{
|
||||
// Find offset at which the next set of numbers stop
|
||||
var numbersEnd = offset + 1;
|
||||
var foundSpaceColumn = false;
|
||||
while (!foundSpaceColumn)
|
||||
{
|
||||
foreach (var line in lines)
|
||||
{
|
||||
// If any line does not contain a space, we can go next offset
|
||||
if (line[numbersEnd] is not ' ')
|
||||
{
|
||||
numbersEnd++;
|
||||
foundSpaceColumn = false;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
foundSpaceColumn = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < numberRows.Count; i++)
|
||||
{
|
||||
var span = lines[i].AsSpan()[offset..numbersEnd];
|
||||
|
||||
// Parse number with correct offset
|
||||
var lastPaddingIndex = span.LastIndexOfAnyExcept(DigitsSearchValue);
|
||||
var lastDigitIndex = span.LastIndexOfAny(DigitsSearchValue);
|
||||
|
||||
if (lastPaddingIndex > lastDigitIndex)
|
||||
{
|
||||
numberRows[i].Add(long.Parse(span) * (int)Math.Pow(10, lastPaddingIndex - lastDigitIndex));
|
||||
}
|
||||
else
|
||||
{
|
||||
numberRows[i].Add(long.Parse(span));
|
||||
}
|
||||
}
|
||||
|
||||
// Also get the symbol
|
||||
symbolRow.Add(lines[4][offset]);
|
||||
|
||||
// Next pack of numbers starts after the space column
|
||||
offset = numbersEnd + 1;
|
||||
}
|
||||
|
||||
// Do the calculations
|
||||
Span<long> numbersBuffer = stackalloc long[4];
|
||||
var count = numberRows[0].Count;
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
numbersBuffer[0] = numberRows[0][i];
|
||||
numbersBuffer[1] = numberRows[1][i];
|
||||
numbersBuffer[2] = numberRows[2][i];
|
||||
numbersBuffer[3] = numberRows[3][i];
|
||||
|
||||
NumbersToRtl(numbersBuffer);
|
||||
|
||||
grandTotal += symbolRow[i] switch
|
||||
{
|
||||
'+' => numbersBuffer[0] + numbersBuffer[1] + numbersBuffer[2] + numbersBuffer[3],
|
||||
'*' => ValueOrIdentity(numbersBuffer[0]) * ValueOrIdentity(numbersBuffer[1]) * ValueOrIdentity(numbersBuffer[2]) * ValueOrIdentity(numbersBuffer[3]),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
|
||||
if (display)
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[green]The grand total is: [yellow]{grandTotal}[/][/]");
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
void NumbersToRtl(Span<long> numbers)
|
||||
{
|
||||
Span<char> number0 = stackalloc char[4];
|
||||
Span<char> number1 = stackalloc char[4];
|
||||
Span<char> number2 = stackalloc char[4];
|
||||
Span<char> number3 = stackalloc char[4];
|
||||
|
||||
numbers[0].TryFormat(number0, out _, "D4");
|
||||
numbers[1].TryFormat(number1, out _, "D4");
|
||||
numbers[2].TryFormat(number2, out _, "D4");
|
||||
numbers[3].TryFormat(number3, out _, "D4");
|
||||
|
||||
// Reconstruct numbers
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
var number = 0;
|
||||
|
||||
if (number0[i] - '0' is not 0 and var digit0)
|
||||
{
|
||||
number = digit0;
|
||||
}
|
||||
|
||||
if (number1[i] - '0' is not 0 and var digit1)
|
||||
{
|
||||
number = (number * 10) + digit1;
|
||||
}
|
||||
|
||||
if (number2[i] - '0' is not 0 and var digit2)
|
||||
{
|
||||
number = (number * 10) + digit2;
|
||||
}
|
||||
|
||||
if (number3[i] - '0' is not 0 and var digit3)
|
||||
{
|
||||
number = (number * 10) + digit3;
|
||||
}
|
||||
|
||||
numbers[i] = number;
|
||||
}
|
||||
}
|
||||
|
||||
long ValueOrIdentity(long value) => value is 0
|
||||
? 1
|
||||
: value;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user