AdventOfCode 2018 Day16 Part2

This commit is contained in:
2023-12-05 04:10:41 +01:00
parent 5e18158a24
commit d3c1a25e67

View File

@@ -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);
}
}
}