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?
|
||||
|
||||
--- 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 string ResolvePart1(string[] inputs)
|
||||
private static (int Index, int Count) MutationTestMachine(string[] inputs, ChronoMachine machine)
|
||||
{
|
||||
int count = 0;
|
||||
int i = 0;
|
||||
ChronoMachine machine = new();
|
||||
bool end = false;
|
||||
int[] beforeRegisters = null;
|
||||
int[] afterRegisters;
|
||||
int[] instruction = null;
|
||||
const string beforeKeyword = "Before: [";
|
||||
const string afterKeyword = "After: [";
|
||||
@@ -110,63 +114,115 @@ public class Day16 : IDay
|
||||
{
|
||||
end = false;
|
||||
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++;
|
||||
|
||||
if (instruction == null || beforeRegisters == null) { continue; }
|
||||
|
||||
if (machine.MutationCheck(instruction[1], instruction[2], instruction[3], beforeRegisters, afterRegisters) >= 3)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
int matches = machine.MutationCheck(instruction[0], instruction[1], instruction[2], instruction[3], beforeRegisters, afterRegisters);
|
||||
if (matches >= 3) { count++; }
|
||||
}
|
||||
else
|
||||
{
|
||||
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++;
|
||||
}
|
||||
|
||||
}
|
||||
return (i, count);
|
||||
}
|
||||
|
||||
public string ResolvePart1(string[] inputs)
|
||||
{
|
||||
ChronoMachine machine = new();
|
||||
(_, int count) = MutationTestMachine(inputs, machine);
|
||||
|
||||
return count.ToString();
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
_registers = new int[4];
|
||||
_instructions = new List<(string OpCode, Action<int, int, int> OpFunc)> {
|
||||
("addr", Op_AddR),
|
||||
("addi", Op_AddI),
|
||||
("mulr", Op_MulR),
|
||||
("muli", Op_MulI),
|
||||
("banr", Op_BAnR),
|
||||
("bani", Op_BAnI),
|
||||
("borr", Op_BOrR),
|
||||
("bori", Op_BOrI),
|
||||
("setr", Op_SetR),
|
||||
("seti", Op_SetI),
|
||||
("gtir", Op_GTIR),
|
||||
("gtri", Op_GTRI),
|
||||
("gtrr", Op_GTRR),
|
||||
("eqir", Op_EqIR),
|
||||
("eqri", Op_EqRI),
|
||||
("eqrr", Op_EqRR),
|
||||
_instructions = new List<ChronoInstruction> {
|
||||
new("addr", Op_AddR),
|
||||
new("addi", Op_AddI),
|
||||
new("mulr", Op_MulR),
|
||||
new("muli", Op_MulI),
|
||||
new("banr", Op_BAnR),
|
||||
new("bani", Op_BAnI),
|
||||
new("borr", Op_BOrR),
|
||||
new("bori", Op_BOrI),
|
||||
new("setr", Op_SetR),
|
||||
new("seti", Op_SetI),
|
||||
new("gtir", Op_GTIR),
|
||||
new("gtri", Op_GTRI),
|
||||
new("gtrr", Op_GTRR),
|
||||
new("eqir", Op_EqIR),
|
||||
new("eqri", Op_EqRI),
|
||||
new("eqrr", Op_EqRR),
|
||||
};
|
||||
}
|
||||
|
||||
public void ResetRegisters()
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
_registers[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetRegisters(int[] registers)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
@@ -184,6 +240,11 @@ public class Day16 : IDay
|
||||
return true;
|
||||
}
|
||||
|
||||
public int GetRegister(int r)
|
||||
{
|
||||
return _registers[r];
|
||||
}
|
||||
|
||||
private void Op_AddR(int a, int b, int c)
|
||||
{
|
||||
_registers[c] = _registers[a] + _registers[b];
|
||||
@@ -264,16 +325,68 @@ public class Day16 : IDay
|
||||
_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;
|
||||
foreach ((string _, Action<int, int, int> OpFunc) in _instructions)
|
||||
foreach (ChronoInstruction instruction in _instructions)
|
||||
{
|
||||
SetRegisters(initialRegisters);
|
||||
OpFunc(a, b, c);
|
||||
if (CheckRegisters(finalRegisters)) { count++; }
|
||||
instruction.OpFunc(a, b, c);
|
||||
if (CheckRegisters(finalRegisters))
|
||||
{
|
||||
instruction.AddPossibleOpCode(opCode);
|
||||
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