Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- void Main()
- {
- //get data
- var aoc = new AdventOfCode(2018, 16);
- //split the input to two seprate
- int split = 0;
- while(!(string.IsNullOrEmpty(aoc.InputLines[split + 0]) &&string.IsNullOrEmpty(aoc.InputLines[split + 1]) && string.IsNullOrEmpty(aoc.InputLines[split + 2])))
- split++;
- var inputA = aoc.InputLines.Take(split).ToArray();
- var inputB = aoc.InputLines.Skip(split + 3).ToArray();
- //alll opcodes
- var opcodes = new[] { "mulr", "addi", "addr", "seti", "muli", "banr", "bani", "bonr", "boni", "setr", "gtir", "gtri", "gtrr", "eqir", "eqri", "eqrr", };
- //dictionary with all the opcodes
- var dicPossibleOpcodes = opcodes.ToDictionary(x => x, _ => Enumerable.Range(0, 16).ToHashSet());
- //inputA = new[] {"Before: [3, 2, 1, 1]", "9 2 1 2", "After: [3, 2, 2, 1]", ""};
- int answerA = 0;
- //check each variant
- for(int i = 0; i < inputA.Length; i +=4)
- {
- int possibleOpCodes = 0;
- var before = ParseBeforeAfter(inputA[i]);
- var after = ParseBeforeAfter(inputA[i + 2]);
- foreach (var opc in opcodes)
- {
- //create copy of before
- var result = before.ToArray();
- //get result
- int opcInt = Execute(inputA[i + 1], result, opc);
- //check
- if (result.Zip(after, (a, b) => a != b).Any(x => x) == false)
- possibleOpCodes++;
- else
- //remove this int as a possible for this opcode
- dicPossibleOpcodes[opc].Remove(opcInt);
- }
- //add to anser a?
- if(possibleOpCodes >= 3) answerA++;
- }
- aoc.SubmitAnswer(answerA, Part.A);
- var dicIntToOpcode = new Dictionary<int, string>();
- //keep going while we have things that are uncertain
- while(dicPossibleOpcodes.Count != 0)
- {
- //get the opcdode we are certain of
- foreach(var found in dicPossibleOpcodes.Where(x=> x.Value.Count == 1).ToArray())
- {
- var commandName = found.Key;
- var commandInt = found.Value.Single();
- //add to the final dic
- dicIntToOpcode.Add(commandInt, commandName);
- //remove it from the dicTodo
- dicPossibleOpcodes.Remove(commandName);
- //remove it from all the other opcodes as possible
- foreach (var kv in dicPossibleOpcodes)
- {
- dicPossibleOpcodes[kv.Key].Remove(commandInt);
- }
- }
- }
- //create registry
- int[] reg = new int[4];
- //test each input of partB
- foreach (var line in inputB)
- {
- //excute each line
- Execute(line, reg, null, dicIntToOpcode);
- }
- aoc.SubmitAnswer(reg[0], Part.B);
- }
- //parse the before after string
- public static int[] ParseBeforeAfter(string line)
- {
- int[] result = new int[4];
- var split = line.Split(',', '[', ']');
- result[0] = int.Parse(split[1].Trim());
- result[1] = int.Parse(split[2].Trim());
- result[2] = int.Parse(split[3].Trim());
- result[3] = int.Parse(split[4].Trim());
- return result;
- }
- //execute a command
- public static int Execute(string line, int[] reg, string opc, Dictionary<int, string> dicTrans = null)
- {
- var split = line.Split(' ');
- var opcInt = int.Parse(split[0]);
- var a = int.Parse(split[1]);
- var b = int.Parse(split[2]);
- var c = int.Parse(split[3]);
- if (dicTrans != null && dicTrans.TryGetValue(opcInt, out opc) == false)
- {
- throw new NotImplementedException();
- }
- switch (opc)
- {
- case "addr": reg[c] = reg[a] + reg[b]; break;
- case "addi": reg[c] = reg[a] + b; break;
- case "mulr": reg[c] = reg[a] * reg[b]; break;
- case "muli": reg[c] = reg[a] * b; break;
- case "banr": reg[c] = reg[a] & reg[b]; break;
- case "bani": reg[c] = reg[a] & b; break;
- case "bonr": reg[c] = reg[a] | reg[b]; break;
- case "boni": reg[c] = reg[a] | b; break;
- case "setr": reg[c] = reg[a]; break;
- case "seti": reg[c] = a; break;
- case "gtir": reg[c] = a > reg[b] ? 1 : 0; break;
- case "gtri": reg[c] = reg[a] > b ? 1 : 0; break;
- case "gtrr": reg[c] = reg[a] > reg[b] ? 1 : 0; break;
- case "eqir": reg[c] = a == reg[b] ? 1 : 0; break;
- case "eqri": reg[c] = reg[a] == b ? 1 : 0; break;
- case "eqrr": reg[c] = reg[a] == reg[b] ? 1 : 0; break;
- default: throw new NotImplementedException();
- }
- return opcInt;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement