aoc2017/csharp/BScottDay18.cs

252 lines
8.4 KiB
C#
Raw Normal View History

2018-12-22 12:50:18 -06:00
using System;
using System.Collections.Generic;
using System.IO;
namespace AOC2017
{
class BScottDay18 : BScottSolution
{
public override string Name => "Day 18: Duet";
public override void Run()
{
string[] exampleInput = new[]
{
"set a 1",
"add a 2",
"mul a a",
"mod a 5",
"snd a",
"set a 0",
"rcv a",
"jgz a -1",
"set a 1",
"jgz a -2"
};
Console.WriteLine($"Part 1 Example Answer: {DuetPart1(exampleInput)}");
string[] exampleInput2 = new[]
{
"snd 1",
"snd 2",
"snd p",
"rcv a",
"rcv b",
"rcv c",
"rcv d"
};
Console.WriteLine($"Part 2 Example Answer: {DuetPart2(exampleInput2)}");
string[] input = File.ReadAllLines("BScottDay18.txt");
Console.WriteLine($"Part 1 Answer: {DuetPart1(input)}");
Console.WriteLine($"Part 2 Answer: {DuetPart2(input)}");
}
private long DuetPart1(string[] instructions)
{
Dictionary<char, long> registers = new Dictionary<char, long>();
// initialize registers
for(char i = 'a'; i <= 'z'; i++)
registers.Add(i,0);
long snd = 0, rcv = 0;
for(int i = 0; i < instructions.Length; i++)
{
string[] args = instructions[i].Split(' ');
long value = 0;
switch (args[0])
{
case "snd":
snd = registers[args[1][0]];
break;
case "set":
if (long.TryParse(args[2], out value))
registers[args[1][0]] = value;
else
registers[args[1][0]] = registers[args[2][0]];
break;
case "add":
if (long.TryParse(args[2], out value))
registers[args[1][0]] += value;
else
registers[args[1][0]] += registers[args[2][0]];
break;
case "mul":
if (long.TryParse(args[2], out value))
registers[args[1][0]] *= value;
else
registers[args[1][0]] *= registers[args[2][0]];
break;
case "mod":
if (long.TryParse(args[2], out value))
registers[args[1][0]] %= value;
else
registers[args[1][0]] %= registers[args[2][0]];
break;
case "rcv":
if (registers[args[1][0]] > 0)
rcv = snd;
break;
case "jgz":
if (!long.TryParse(args[1], out value))
value = registers[args[1][0]];
if (value > 0)
{
if (!long.TryParse(args[2], out value))
value = registers[args[2][0]];
i += (int)(value-1);
}
break;
}
// recover operation ran
if (rcv > 0)
break;
}
return rcv;
}
private long DuetPart2(string[] instructions)
{
Queue<long> programQueue0 = new Queue<long>();
Queue<long> programQueue1 = new Queue<long>();
Program program0 = new Program(0, instructions, programQueue0, programQueue1);
Program program1 = new Program(1, instructions, programQueue1, programQueue0);
while (!program0.Finished && !program1.Finished)
{
program0.RunInstruction();
program1.RunInstruction();
if (program0.PendingReceive && program1.PendingReceive)
break;
}
return program1.SendCount;
}
class Program
{
Dictionary<char, long> registers = new Dictionary<char, long>();
private long pc = 0;
private long sendCount = 0;
private string[] instructions;
private Queue<long> inputQueue;
private Queue<long> outputQueue;
private bool pendingReceive = false;
private bool finished = false;
public bool PendingReceive
{
get { return pendingReceive; }
}
public bool Finished
{
get { return finished; }
}
public long SendCount
{
get { return sendCount; }
}
public Program(int programId, string[] instructions, Queue<long> inputQueue, Queue<long> outputQueue)
{
for (char i = 'a'; i <= 'z'; i++)
this.registers.Add(i, 0);
this.registers['p'] = programId;
this.instructions = instructions;
this.inputQueue = inputQueue;
this.outputQueue = outputQueue;
}
public void RunInstruction()
{
string[] args = instructions[pc].Split(' ');
long value = 0;
switch (args[0])
{
case "snd":
sendCount++;
if (long.TryParse(args[1], out value))
outputQueue.Enqueue(value);
else
outputQueue.Enqueue(registers[args[1][0]]);
break;
case "set":
if (long.TryParse(args[2], out value))
registers[args[1][0]] = value;
else
registers[args[1][0]] = registers[args[2][0]];
break;
case "add":
if (long.TryParse(args[2], out value))
registers[args[1][0]] += value;
else
registers[args[1][0]] += registers[args[2][0]];
break;
case "mul":
if (long.TryParse(args[2], out value))
registers[args[1][0]] *= value;
else
registers[args[1][0]] *= registers[args[2][0]];
break;
case "mod":
if (long.TryParse(args[2], out value))
registers[args[1][0]] %= value;
else
registers[args[1][0]] %= registers[args[2][0]];
break;
case "rcv":
if (inputQueue.Count == 0)
{
pendingReceive = true;
return;
}
registers[args[1][0]] = inputQueue.Dequeue();
break;
case "jgz":
if (!long.TryParse(args[1], out value))
value = registers[args[1][0]];
if (value > 0)
{
if (!long.TryParse(args[2], out value))
value = registers[args[2][0]];
pc += value;
return;
}
break;
}
if (++pc > instructions.Length)
{
finished = true;
return;
}
}
}
}
}