Files
AdventOfCode/AdventOfCode/Problems/AOC2022/Day5/SupplyStacks.cs
2025-12-01 21:21:14 -05:00

131 lines
3.6 KiB
C#

using AdventOfCode.Runner.Attributes;
using Superpower;
using Superpower.Parsers;
using System.Text.RegularExpressions;
namespace AdventOfCode.Problems.AOC2022.Day5;
[ProblemInfo(2022, 5, "Supply Stacks")]
internal partial class SupplyStacks : Problem
{
private List<char>[] _stacksPart1 = Array.Empty<List<char>>();
private List<char>[] _stacksPart2 = Array.Empty<List<char>>();
private readonly TextParser<(int, int, int)> _moveParser = from move in Character.Letter.Or(Character.WhiteSpace).Many()
from stack in Character.Digit.Many()
from frm in Character.Letter.Or(Character.WhiteSpace).Many()
from source in Character.Digit.Many()
from to in Character.Letter.Or(Character.WhiteSpace).Many()
from dst in Character.Digit.Many()
select (int.Parse(stack), int.Parse(source), int.Parse(dst));
private List<(int stack, int from, int to)> _moves = new();
public override void CalculatePart1()
{
foreach (var move in _moves)
{
PerformBasicMove(_stacksPart1, move);
}
Part1 = new string(_stacksPart1.Select(b => b.Last()).ToArray());
}
private static void PerformBasicMove(List<char>[] data, (int stack, int from, int to) move)
{
var from = data[move.from - 1];
var to = data[move.to - 1];
for (int i = 0; i < move.stack; i++)
{
var item = from[^1];
from.RemoveAt(from.Count - 1);
to.Add(item);
}
}
private static void PerformMove(List<char>[] data, (int stack, int from, int to) move)
{
var from = data[move.from - 1];
var to = data[move.to - 1];
var items = from.Skip(from.Count - move.stack);
to.AddRange(items);
from.RemoveRange(from.Count - move.stack, move.stack);
}
public override void CalculatePart2()
{
foreach (var move in _moves)
{
PerformMove(_stacksPart2, move);
}
Part2 = new string(_stacksPart2.Select(b => b.Last()).ToArray());
}
public override void LoadInput()
{
var lines = ReadInputLines("input.txt");
var readMoves = false;
var buffers = new List<List<char>>();
var moves = new List<(int stack, int from, int to)>();
foreach (var line in lines)
{
if (string.IsNullOrWhiteSpace(line))
{
readMoves = true;
continue;
}
if (readMoves)
{
moves.Add(ParseMoveLineRegex(line));
}
else
{
var crates = ParseCrateLine(line);
for (int i = 0; i < crates.Count; i++)
{
var crate = crates[i];
if (buffers.Count == i)
buffers.Add(crate == ' ' ? new() : new List<char>() { crate });
else if (crate != ' ')
buffers[i].Add(crate);
}
}
}
_stacksPart1 = buffers.Select(b => b.Take(b.Count - 1).Reverse().ToList()).ToArray();
_stacksPart2 = buffers.Select(b => b.Take(b.Count - 1).Reverse().ToList()).ToArray();
_moves = moves;
}
//Way slower
private (int stack, int from, int to) ParseMoveLine(string line)
{
return _moveParser.Parse(line);
}
private static (int stack, int from, int to) ParseMoveLineRegex(string line)
{
var r = MoveParser().Matches(line);
var items = r.First()
.Groups.Values.Skip(1)
.Select(v => int.Parse(v.ValueSpan))
.ToArray();
return (items[0], items[1], items[2]);
}
private static List<char> ParseCrateLine(string line)
{
var result = new List<char>(line.Length / 4);
for (int i = 1; i < line.Length; i += 4)
{
var c = line[i];
result.Add(c);
}
return result;
}
[GeneratedRegex("move (\\d+) from (\\d+) to (\\d+)")]
private static partial Regex MoveParser();
}