From d3c1a25e670eb0f1312126323b069d27de89b554 Mon Sep 17 00:00:00 2001 From: "Valeriano A.R." Date: Tue, 5 Dec 2023 04:10:41 +0100 Subject: [PATCH] AdventOfCode 2018 Day16 Part2 --- AdventOfCode2018/Day16.cs | 187 ++++++++++++++++++++++++++++++-------- 1 file changed, 150 insertions(+), 37 deletions(-) diff --git a/AdventOfCode2018/Day16.cs b/AdventOfCode2018/Day16.cs index 0fbd800..016b3ae 100644 --- a/AdventOfCode2018/Day16.cs +++ b/AdventOfCode2018/Day16.cs @@ -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 OpFunc)> _instructions; + private readonly List _instructions; + + private class ChronoInstruction + { + public int OpCode { get; set; } = -1; + public string OpName { get; } + public Action OpFunc { get; } + + public ChronoInstruction(string opName, Action opFunc) + { + OpName = opName; + OpFunc = opFunc; + } + + public Dictionary 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 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 { + 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 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 _dictInstructions = new(); + + public void InitOpCodes(bool debug = false) + { + if(debug) + { + foreach (ChronoInstruction instruction in _instructions) + { + Console.Write($"{instruction.OpName}: "); + foreach (KeyValuePair 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 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); + } } } \ No newline at end of file