Advertisement
Equd

AdventOfCode 2018 Day 16

Dec 16th, 2018
222
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.01 KB | None | 0 0
  1. void Main()
  2. {
  3.     //get data
  4.     var aoc = new AdventOfCode(2018, 16);
  5.    
  6.     //split the input to two seprate
  7.     int split = 0;
  8.     while(!(string.IsNullOrEmpty(aoc.InputLines[split + 0]) &&string.IsNullOrEmpty(aoc.InputLines[split + 1]) &&    string.IsNullOrEmpty(aoc.InputLines[split + 2])))
  9.         split++;
  10.     var inputA = aoc.InputLines.Take(split).ToArray();
  11.     var inputB = aoc.InputLines.Skip(split + 3).ToArray();
  12.  
  13.     //alll opcodes
  14.     var opcodes = new[] { "mulr", "addi", "addr", "seti", "muli", "banr", "bani", "bonr", "boni", "setr", "gtir", "gtri", "gtrr", "eqir", "eqri", "eqrr", };
  15.  
  16.     //dictionary with all the opcodes
  17.     var dicPossibleOpcodes = opcodes.ToDictionary(x => x, _ => Enumerable.Range(0, 16).ToHashSet());
  18.    
  19.     //inputA = new[] {"Before: [3, 2, 1, 1]", "9 2 1 2", "After:  [3, 2, 2, 1]", ""};
  20.    
  21.     int answerA = 0;
  22.    
  23.     //check each variant
  24.     for(int i = 0; i < inputA.Length; i +=4)
  25.     {
  26.         int possibleOpCodes = 0;
  27.         var before = ParseBeforeAfter(inputA[i]);
  28.         var after = ParseBeforeAfter(inputA[i + 2]);
  29.  
  30.         foreach (var opc in opcodes)
  31.         {
  32.             //create copy of before
  33.             var result = before.ToArray();
  34.  
  35.             //get result
  36.             int opcInt = Execute(inputA[i + 1], result, opc);
  37.  
  38.             //check
  39.             if (result.Zip(after, (a, b) => a != b).Any(x => x) == false)          
  40.                 possibleOpCodes++;
  41.             else
  42.                 //remove this int as a possible for this opcode
  43.                 dicPossibleOpcodes[opc].Remove(opcInt);
  44.         }
  45.        
  46.         //add to anser a?
  47.         if(possibleOpCodes >= 3) answerA++;
  48.     }
  49.        
  50.     aoc.SubmitAnswer(answerA, Part.A);
  51.        
  52.     var dicIntToOpcode = new Dictionary<int, string>();
  53.    
  54.     //keep going while we have things that are uncertain
  55.     while(dicPossibleOpcodes.Count != 0)
  56.     {
  57.         //get the opcdode we are certain of
  58.         foreach(var found in dicPossibleOpcodes.Where(x=> x.Value.Count == 1).ToArray())
  59.         {
  60.             var commandName = found.Key;
  61.             var commandInt = found.Value.Single();
  62.            
  63.             //add to the final dic
  64.             dicIntToOpcode.Add(commandInt, commandName);
  65.            
  66.             //remove it from the dicTodo
  67.             dicPossibleOpcodes.Remove(commandName);
  68.            
  69.             //remove it from all the other opcodes as possible
  70.             foreach (var kv in dicPossibleOpcodes)
  71.             {
  72.                 dicPossibleOpcodes[kv.Key].Remove(commandInt);
  73.             }          
  74.         }
  75.     }
  76.    
  77.     //create registry
  78.     int[] reg = new int[4];
  79.    
  80.     //test each input of partB
  81.     foreach (var line in inputB)
  82.     {
  83.         //excute each line
  84.         Execute(line, reg, null, dicIntToOpcode);
  85.     }
  86.  
  87.     aoc.SubmitAnswer(reg[0], Part.B);
  88. }
  89.  
  90. //parse the before after string
  91. public static int[] ParseBeforeAfter(string line)
  92. {
  93.     int[] result = new int[4];     
  94.     var split = line.Split(',', '[', ']');
  95.  
  96.     result[0] = int.Parse(split[1].Trim());
  97.     result[1] = int.Parse(split[2].Trim());
  98.     result[2] = int.Parse(split[3].Trim());
  99.     result[3] = int.Parse(split[4].Trim());
  100.  
  101.     return result;
  102. }
  103.  
  104. //execute a command
  105. public static int Execute(string line, int[] reg, string opc, Dictionary<int, string> dicTrans = null)
  106. {
  107.     var split = line.Split(' ');
  108.     var opcInt = int.Parse(split[0]);
  109.     var a = int.Parse(split[1]);
  110.     var b = int.Parse(split[2]);
  111.     var c = int.Parse(split[3]);
  112.  
  113.     if (dicTrans != null && dicTrans.TryGetValue(opcInt, out opc) == false)
  114.     {
  115.         throw new NotImplementedException();
  116.     }
  117.  
  118.     switch (opc)
  119.     {
  120.         case "addr": reg[c] = reg[a] + reg[b]; break;
  121.         case "addi": reg[c] = reg[a] + b; break;
  122.  
  123.         case "mulr": reg[c] = reg[a] * reg[b]; break;
  124.         case "muli": reg[c] = reg[a] * b; break;
  125.  
  126.         case "banr": reg[c] = reg[a] & reg[b]; break;
  127.         case "bani": reg[c] = reg[a] & b; break;
  128.  
  129.         case "bonr": reg[c] = reg[a] | reg[b]; break;
  130.         case "boni": reg[c] = reg[a] | b; break;
  131.  
  132.         case "setr": reg[c] = reg[a]; break;
  133.         case "seti": reg[c] = a; break;
  134.  
  135.         case "gtir": reg[c] = a > reg[b] ? 1 : 0; break;
  136.         case "gtri": reg[c] = reg[a] > b ? 1 : 0; break;
  137.         case "gtrr": reg[c] = reg[a] > reg[b] ? 1 : 0; break;
  138.  
  139.         case "eqir": reg[c] = a == reg[b] ? 1 : 0; break;
  140.         case "eqri": reg[c] = reg[a] == b ? 1 : 0; break;
  141.         case "eqrr": reg[c] = reg[a] == reg[b] ? 1 : 0; break;
  142.  
  143.         default: throw new NotImplementedException();
  144.     }
  145.     return opcInt;
  146. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement