// See https://aka.ms/new-console-template for more information Console.WriteLine("Hello, World!"); var exampleInstructions01 = Instruction.LoadInstructions("example-input1.txt"); var exampleInstructions02 = Instruction.LoadInstructions("example-input2.txt"); var puzzleInstructions = Instruction.LoadInstructions("puzzle-input.txt"); // Part 01 outputSignalStrength(exampleInstructions02, 20, 40); outputSignalStrength(puzzleInstructions, 20, 40); // Part 02 Console.Write(" === Writing Example Output === "); renderOnCrt(exampleInstructions02); Console.WriteLine(); Console.WriteLine(); Console.Write(" === Writing Puzzle Output === "); renderOnCrt(puzzleInstructions); Console.WriteLine(); bool ShouldDrawSprite(int position, int cycle) { return (position + 0) % 40 == cycle % 40 || (position - 1) % 40 == cycle % 40 || (position + 1) % 40 == cycle % 40; } void Draw(int spritePosition, CPU cpu) { if (cpu.Cycle % 40 == 0) Console.WriteLine(); if (ShouldDrawSprite(spritePosition, cpu.Cycle)) { Console.Write('#'); } else { Console.Write('.'); } } void renderOnCrt(List instructions) { int spritePosition; CPU cpu = new CPU(); foreach (var i in instructions) { spritePosition = cpu.GetRegisterValue('X'); if (i.CycleCount() == 1) { Draw(spritePosition, cpu); cpu.Execute(i); } else if (i.CycleCount() == 2) { Draw(spritePosition, cpu); cpu.Cycle++; Draw(spritePosition, cpu); cpu.Execute(i); cpu.Cycle--; } else throw new InvalidDataException(); } } void outputSignalStrength(List list, int init, int step) { CPU cpu = new CPU(); int nextSignal = init; List strengthList = new List(); Console.WriteLine(" === Listing signals ==="); foreach (var l in list) { int oldValue = cpu.GetRegisterValue('X'); cpu.Execute(l); if (cpu.Cycle >= nextSignal) { int strength = nextSignal * oldValue; Console.WriteLine(String.Format("Cycle({0}): SignalStrength({1})", nextSignal, strength)); strengthList.Add(strength); nextSignal += step; } } int strengthSum = 0; foreach (var s in strengthList) { strengthSum += s; } Console.WriteLine("Strength Sum: " + strengthSum); Console.WriteLine(); } class CPU { public int Cycle { get; set; } private int registerX; public CPU() { Cycle = 0; registerX = 1; } public int GetRegisterValue(char registerName) { switch (registerName) { case 'X': return registerX; default: throw new ArgumentException(); } } public void SetRegisterValue(char registerName, int value) { switch (registerName) { case 'X': registerX = value; break; default: throw new ArgumentException(); } } public void Execute(Instruction i) { i.Execute(this); } } abstract class Instruction { public virtual void Execute(CPU cpu, params int[] list) { cpu.Cycle += CycleCount(); } public abstract int CycleCount(); static Instruction ParseInstruction(string line) { if (line.StartsWith("noop")) { return new NoopInstruction(); } if (line.StartsWith("addx")) { var split = line.Split(' '); return new AddInstruction('X', Int32.Parse(split[1])); } throw new InvalidDataException(); } public static List LoadInstructions(string filename) { List list = new List(); using (StreamReader reader = System.IO.File.OpenText(filename)) { while (!reader.EndOfStream) { string? line = reader.ReadLine(); if (line == null) throw new InvalidDataException(); list.Add(ParseInstruction(line)); } } return list; } } class NoopInstruction : Instruction { public override void Execute(CPU cpu, params int[] list) { base.Execute(cpu, list); } public override int CycleCount() { return 1; } } class AddInstruction : Instruction { public AddInstruction(char register, int value) { Value = value; Register = register; } public int Value { get; set; } public char Register { get; set; } public override void Execute(CPU cpu, params int[] list) { base.Execute(cpu, list); cpu.SetRegisterValue(Register, cpu.GetRegisterValue(Register) + Value); } public override int CycleCount() { return 2; } }