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[] 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 Operations { get; set; } = new List(); 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[length]; for (int i = 0; i < Crates.Length; i++) { Crates[i] = new List(); } } // 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]))); } } } }