231 lines
5.2 KiB
C#
231 lines
5.2 KiB
C#
// 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<Instruction> 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<Instruction> list, int init, int step)
|
|
{
|
|
CPU cpu = new CPU();
|
|
int nextSignal = init;
|
|
List<int> strengthList = new List<int>();
|
|
|
|
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<Instruction> LoadInstructions(string filename)
|
|
{
|
|
List<Instruction> list = new List<Instruction>();
|
|
|
|
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;
|
|
}
|
|
} |