233 lines
7.1 KiB
C#
233 lines
7.1 KiB
C#
|
|
using System.Net;
|
|
using System.Runtime.CompilerServices;
|
|
using static LoadedData;
|
|
|
|
const string puzzleFileName = @"puzzle-input.txt";
|
|
const string exampleFileName = @"example-input.txt";
|
|
|
|
Part01();
|
|
Part02();
|
|
|
|
|
|
static void Part01()
|
|
{
|
|
Console.WriteLine("\n****** UNORDERED ******\n");
|
|
|
|
var exampleData = new LoadedData(exampleFileName);
|
|
var puzzleData = new LoadedData(puzzleFileName);
|
|
|
|
Console.WriteLine("exmample top crates");
|
|
exampleData.PrintTopCrates();
|
|
Console.WriteLine("performing ops");
|
|
exampleData.PerformOperationsUnordered(exampleData.Operations.Count);
|
|
Console.WriteLine("exmample top crates");
|
|
exampleData.PrintTopCrates();
|
|
|
|
Console.WriteLine("\n****** PUZZLE ******\n");
|
|
|
|
Console.WriteLine("puzzle top crates");
|
|
puzzleData.PrintTopCrates();
|
|
Console.WriteLine("performing ops");
|
|
puzzleData.PerformOperationsUnordered(puzzleData.Operations.Count);
|
|
Console.WriteLine("puzzle top crates");
|
|
puzzleData.PrintTopCrates();
|
|
}
|
|
|
|
static void Part02()
|
|
{
|
|
Console.WriteLine("\n****** ORDERED ******\n");
|
|
|
|
var exampleData = new LoadedData(exampleFileName);
|
|
var puzzleData = new LoadedData(puzzleFileName);
|
|
|
|
Console.WriteLine("exmample top crates");
|
|
exampleData.PrintTopCrates();
|
|
Console.WriteLine("performing ops");
|
|
exampleData.PerformOperationsOrdered(exampleData.Operations.Count);
|
|
Console.WriteLine("exmample top crates");
|
|
exampleData.PrintTopCrates();
|
|
|
|
Console.WriteLine("\n****** PUZZLE ******\n");
|
|
|
|
Console.WriteLine("puzzle top crates");
|
|
puzzleData.PrintTopCrates();
|
|
Console.WriteLine("performing ops");
|
|
puzzleData.PerformOperationsOrdered(puzzleData.Operations.Count);
|
|
Console.WriteLine("puzzle top crates");
|
|
puzzleData.PrintTopCrates();
|
|
}
|
|
|
|
class LoadedData
|
|
{
|
|
public class Crate
|
|
{
|
|
public Crate(char c)
|
|
{
|
|
Name = c;
|
|
}
|
|
public char Name { get; set; }
|
|
}
|
|
|
|
public List<Crate>[] Crates { get; set; }
|
|
public int StackCount { get { return Crates.Length; } }
|
|
|
|
public class Operation
|
|
{
|
|
public Operation(int crateCount, int sourceStack, int destinationStack)
|
|
{
|
|
CrateCount = crateCount;
|
|
SourceStack = sourceStack;
|
|
DestinationStack = destinationStack;
|
|
}
|
|
|
|
public int CrateCount { get; set; }
|
|
public int SourceStack { get; set; }
|
|
public int DestinationStack { get; set; }
|
|
}
|
|
|
|
public List<Operation> Operations { get; set; } = new List<Operation>();
|
|
private int operationIndex = 0;
|
|
|
|
public void PrintTopCrates()
|
|
{
|
|
string printout = "";
|
|
foreach (var stack in Crates)
|
|
{
|
|
printout += String.Format("{0}", stack[stack.Count - 1].Name);
|
|
}
|
|
|
|
Console.WriteLine(printout);
|
|
}
|
|
|
|
public void PerformOperationsUnordered(int count)
|
|
{
|
|
if (operationIndex + count > Operations.Count)
|
|
{
|
|
throw new ArgumentOutOfRangeException("Too many operations requested");
|
|
}
|
|
|
|
if (count > 0)
|
|
{
|
|
for (; operationIndex < Operations.Count; operationIndex++)
|
|
{
|
|
Operation op = Operations[operationIndex];
|
|
|
|
for (int i = 0; i < op.CrateCount; i++)
|
|
{
|
|
int sourceIndex = op.SourceStack - 1;
|
|
int destinationIndex = op.DestinationStack - 1;
|
|
|
|
var crate = Crates[sourceIndex][Crates[sourceIndex].Count - 1];
|
|
Crates[sourceIndex].RemoveAt(Crates[sourceIndex].Count - 1);
|
|
Crates[destinationIndex].Add(crate);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void PerformOperationsOrdered(int count)
|
|
{
|
|
if (operationIndex + count > Operations.Count)
|
|
{
|
|
throw new ArgumentOutOfRangeException("Too many operations requested");
|
|
}
|
|
|
|
if (count > 0)
|
|
{
|
|
for (; operationIndex < Operations.Count; operationIndex++)
|
|
{
|
|
Operation op = Operations[operationIndex];
|
|
|
|
int sourceIndex = op.SourceStack - 1;
|
|
int destinationIndex = op.DestinationStack - 1;
|
|
int destStackIndex = Crates[destinationIndex].Count;
|
|
|
|
for (int i = 0; i < op.CrateCount; i++)
|
|
{
|
|
var crate = Crates[sourceIndex][Crates[sourceIndex].Count - 1];
|
|
Crates[sourceIndex].RemoveAt(Crates[sourceIndex].Count - 1);
|
|
Crates[destinationIndex].Insert(destStackIndex, crate);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public LoadedData(string fileName)
|
|
{
|
|
using (StreamReader reader = File.OpenText(fileName))
|
|
{
|
|
while (!reader.EndOfStream)
|
|
{
|
|
string? line = reader.ReadLine();
|
|
|
|
if (line == null || (line.Length+1) % 4 != 0)
|
|
{
|
|
throw new InvalidDataException();
|
|
}
|
|
|
|
// It's the first line, create the list
|
|
if (Crates == null)
|
|
{
|
|
int length = (line.Length+1) / 4;
|
|
Crates = new List<Crate>[length];
|
|
for (int i = 0; i < Crates.Length; i++)
|
|
{
|
|
Crates[i] = new List<Crate>();
|
|
}
|
|
}
|
|
|
|
// Validate line length
|
|
if ((StackCount*4)-1 > line.Length)
|
|
{
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
|
|
// Check for the crate number line
|
|
if (Char.IsAsciiDigit(line[1]))
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Read in each crate
|
|
for (int i = 0; i < StackCount; i++)
|
|
{
|
|
// Read in the entry
|
|
char c = line[(i * 4) + 1];
|
|
|
|
if (c != ' ')
|
|
{
|
|
if (!Char.IsLetter(c))
|
|
{
|
|
throw new InvalidDataException();
|
|
}
|
|
|
|
Crates[i].Insert(0, new Crate(c));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Read in the empty line
|
|
reader.ReadLine();
|
|
|
|
while (!reader.EndOfStream)
|
|
{
|
|
string? line = reader.ReadLine();
|
|
|
|
if (line == null)
|
|
{
|
|
throw new InvalidDataException();
|
|
}
|
|
|
|
var split = line.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
|
|
|
if (split.Length < 5)
|
|
{
|
|
throw new InvalidDataException();
|
|
}
|
|
|
|
Operations.Add(new Operation(Int32.Parse(split[1]), Int32.Parse(split[3]), Int32.Parse(split[5])));
|
|
}
|
|
}
|
|
}
|
|
} |