209 lines
6.1 KiB
C#
209 lines
6.1 KiB
C#
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;
|
|
}
|
|
} |