AdventOfCode 2018 Day16 Part2
This commit is contained in:
@@ -76,18 +76,22 @@ You collect many of these samples (the first section of your puzzle input). The
|
|||||||
|
|
||||||
Ignoring the opcode numbers, how many samples in your puzzle input behave like three or more opcodes?
|
Ignoring the opcode numbers, how many samples in your puzzle input behave like three or more opcodes?
|
||||||
|
|
||||||
|
--- Part Two ---
|
||||||
|
|
||||||
|
Using the samples you collected, work out the number of each opcode and execute the test program (the second section of your puzzle input).
|
||||||
|
|
||||||
|
What value is contained in register 0 after executing the test program?
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Day16 : IDay
|
public class Day16 : IDay
|
||||||
{
|
{
|
||||||
public string ResolvePart1(string[] inputs)
|
private static (int Index, int Count) MutationTestMachine(string[] inputs, ChronoMachine machine)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
ChronoMachine machine = new();
|
|
||||||
bool end = false;
|
bool end = false;
|
||||||
int[] beforeRegisters = null;
|
int[] beforeRegisters = null;
|
||||||
int[] afterRegisters;
|
|
||||||
int[] instruction = null;
|
int[] instruction = null;
|
||||||
const string beforeKeyword = "Before: [";
|
const string beforeKeyword = "Before: [";
|
||||||
const string afterKeyword = "After: [";
|
const string afterKeyword = "After: [";
|
||||||
@@ -110,63 +114,115 @@ public class Day16 : IDay
|
|||||||
{
|
{
|
||||||
end = false;
|
end = false;
|
||||||
string strBeforeRegisters = inputs[i].Substring(afterKeyword.Length, inputs[i].Length - (1 + afterKeyword.Length));
|
string strBeforeRegisters = inputs[i].Substring(afterKeyword.Length, inputs[i].Length - (1 + afterKeyword.Length));
|
||||||
afterRegisters = strBeforeRegisters.Split(", ").Select(s => Convert.ToInt32(s)).ToArray();
|
int[] afterRegisters = strBeforeRegisters.Split(", ").Select(s => Convert.ToInt32(s)).ToArray();
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
if (instruction == null || beforeRegisters == null) { continue; }
|
if (instruction == null || beforeRegisters == null) { continue; }
|
||||||
|
|
||||||
if (machine.MutationCheck(instruction[1], instruction[2], instruction[3], beforeRegisters, afterRegisters) >= 3)
|
int matches = machine.MutationCheck(instruction[0], instruction[1], instruction[2], instruction[3], beforeRegisters, afterRegisters);
|
||||||
{
|
if (matches >= 3) { count++; }
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
end = false;
|
end = false;
|
||||||
instruction = inputs[i].Split(" ").Where(s => string.IsNullOrEmpty(s) == false).Select(s => Convert.ToInt32(s)).ToArray();
|
instruction = inputs[i].Split(" ").Select(s => Convert.ToInt32(s)).ToArray();
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return (i, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ResolvePart1(string[] inputs)
|
||||||
|
{
|
||||||
|
ChronoMachine machine = new();
|
||||||
|
(_, int count) = MutationTestMachine(inputs, machine);
|
||||||
|
|
||||||
return count.ToString();
|
return count.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ResolvePart2(string[] inputs)
|
public string ResolvePart2(string[] inputs)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
ChronoMachine machine = new();
|
||||||
|
(int i, _) = MutationTestMachine(inputs, machine);
|
||||||
|
i++;
|
||||||
|
machine.InitOpCodes();
|
||||||
|
machine.ResetRegisters();
|
||||||
|
while (inputs.Length > i)
|
||||||
|
{
|
||||||
|
string line = inputs[i];
|
||||||
|
i++;
|
||||||
|
if (string.IsNullOrEmpty(line)) { continue; }
|
||||||
|
int[] instruction = line.Split(" ").Select(s => Convert.ToInt32(s)).ToArray();
|
||||||
|
machine.ExecInstruction(instruction[0], instruction[1], instruction[2], instruction[3]);
|
||||||
|
}
|
||||||
|
return machine.GetRegister(0).ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ChronoMachine
|
private class ChronoMachine
|
||||||
{
|
{
|
||||||
private int[] _registers;
|
private readonly int[] _registers;
|
||||||
|
|
||||||
private List<(string OpCode, Action<int, int, int> OpFunc)> _instructions;
|
private readonly List<ChronoInstruction> _instructions;
|
||||||
|
|
||||||
|
private class ChronoInstruction
|
||||||
|
{
|
||||||
|
public int OpCode { get; set; } = -1;
|
||||||
|
public string OpName { get; }
|
||||||
|
public Action<int, int, int> OpFunc { get; }
|
||||||
|
|
||||||
|
public ChronoInstruction(string opName, Action<int, int, int> opFunc)
|
||||||
|
{
|
||||||
|
OpName = opName;
|
||||||
|
OpFunc = opFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<int, int> OpCodeHistogram { get; } = new();
|
||||||
|
|
||||||
|
public void AddPossibleOpCode(int opCode)
|
||||||
|
{
|
||||||
|
if (OpCodeHistogram.TryGetValue(opCode, out int value))
|
||||||
|
{
|
||||||
|
value++;
|
||||||
|
OpCodeHistogram[opCode] = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OpCodeHistogram.Add(opCode, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public ChronoMachine()
|
public ChronoMachine()
|
||||||
{
|
{
|
||||||
_registers = new int[4];
|
_registers = new int[4];
|
||||||
_instructions = new List<(string OpCode, Action<int, int, int> OpFunc)> {
|
_instructions = new List<ChronoInstruction> {
|
||||||
("addr", Op_AddR),
|
new("addr", Op_AddR),
|
||||||
("addi", Op_AddI),
|
new("addi", Op_AddI),
|
||||||
("mulr", Op_MulR),
|
new("mulr", Op_MulR),
|
||||||
("muli", Op_MulI),
|
new("muli", Op_MulI),
|
||||||
("banr", Op_BAnR),
|
new("banr", Op_BAnR),
|
||||||
("bani", Op_BAnI),
|
new("bani", Op_BAnI),
|
||||||
("borr", Op_BOrR),
|
new("borr", Op_BOrR),
|
||||||
("bori", Op_BOrI),
|
new("bori", Op_BOrI),
|
||||||
("setr", Op_SetR),
|
new("setr", Op_SetR),
|
||||||
("seti", Op_SetI),
|
new("seti", Op_SetI),
|
||||||
("gtir", Op_GTIR),
|
new("gtir", Op_GTIR),
|
||||||
("gtri", Op_GTRI),
|
new("gtri", Op_GTRI),
|
||||||
("gtrr", Op_GTRR),
|
new("gtrr", Op_GTRR),
|
||||||
("eqir", Op_EqIR),
|
new("eqir", Op_EqIR),
|
||||||
("eqri", Op_EqRI),
|
new("eqri", Op_EqRI),
|
||||||
("eqrr", Op_EqRR),
|
new("eqrr", Op_EqRR),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ResetRegisters()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
_registers[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void SetRegisters(int[] registers)
|
private void SetRegisters(int[] registers)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
@@ -184,6 +240,11 @@ public class Day16 : IDay
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int GetRegister(int r)
|
||||||
|
{
|
||||||
|
return _registers[r];
|
||||||
|
}
|
||||||
|
|
||||||
private void Op_AddR(int a, int b, int c)
|
private void Op_AddR(int a, int b, int c)
|
||||||
{
|
{
|
||||||
_registers[c] = _registers[a] + _registers[b];
|
_registers[c] = _registers[a] + _registers[b];
|
||||||
@@ -264,16 +325,68 @@ public class Day16 : IDay
|
|||||||
_registers[c] = (_registers[a] == _registers[b]) ? 1 : 0;
|
_registers[c] = (_registers[a] == _registers[b]) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int MutationCheck(int a, int b, int c, int[] initialRegisters, int[] finalRegisters)
|
public int MutationCheck(int opCode, int a, int b, int c, int[] initialRegisters, int[] finalRegisters)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
foreach ((string _, Action<int, int, int> OpFunc) in _instructions)
|
foreach (ChronoInstruction instruction in _instructions)
|
||||||
{
|
{
|
||||||
SetRegisters(initialRegisters);
|
SetRegisters(initialRegisters);
|
||||||
OpFunc(a, b, c);
|
instruction.OpFunc(a, b, c);
|
||||||
if (CheckRegisters(finalRegisters)) { count++; }
|
if (CheckRegisters(finalRegisters))
|
||||||
|
{
|
||||||
|
instruction.AddPossibleOpCode(opCode);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly Dictionary<int, ChronoInstruction> _dictInstructions = new();
|
||||||
|
|
||||||
|
public void InitOpCodes(bool debug = false)
|
||||||
|
{
|
||||||
|
if(debug)
|
||||||
|
{
|
||||||
|
foreach (ChronoInstruction instruction in _instructions)
|
||||||
|
{
|
||||||
|
Console.Write($"{instruction.OpName}: ");
|
||||||
|
foreach (KeyValuePair<int, int> pair in instruction.OpCodeHistogram)
|
||||||
|
{
|
||||||
|
Console.Write($"{pair.Key}->{pair.Value} ");
|
||||||
|
}
|
||||||
|
Console.WriteLine(string.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (_instructions.Any(i => i.OpCode == -1))
|
||||||
|
{
|
||||||
|
foreach (ChronoInstruction instruction in _instructions)
|
||||||
|
{
|
||||||
|
if (instruction.OpCode != -1) { continue; }
|
||||||
|
int opCode = -1;
|
||||||
|
foreach (KeyValuePair<int, int> pair in instruction.OpCodeHistogram)
|
||||||
|
{
|
||||||
|
if (_dictInstructions.ContainsKey(pair.Key)) { continue; }
|
||||||
|
|
||||||
|
if (opCode == -1) { opCode = pair.Key; }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
opCode = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (opCode == -1) { continue; }
|
||||||
|
|
||||||
|
instruction.OpCode = opCode;
|
||||||
|
_dictInstructions.Add(opCode, instruction);
|
||||||
|
if(debug) { Console.WriteLine($"{instruction.OpName}: {instruction.OpCode}"); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExecInstruction(int opCode, int a, int b, int c)
|
||||||
|
{
|
||||||
|
ChronoInstruction instruction = _dictInstructions[opCode];
|
||||||
|
instruction.OpFunc(a, b, c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user