Equd

AOC IntComputer

Dec 9th, 2019
595
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.63 KB | None | 0 0
  1.  
  2. public enum ParameterMode { Position = 0, Immidiat = 1, Relative = 2 }
  3. public class IntCode
  4. {
  5.     static long cpuCount = 1;
  6.     static bool debug = false;
  7.    
  8.     public int steps { get; private set; }
  9.    
  10.     public long cpuID { get;}
  11.     public long lastOutput {get; private set; }
  12.     public long lastOpCode {get; private set; }
  13.     public bool pauseOnOutput {get;}
  14.    
  15.     public Dictionary<long, long> dic;
  16.  
  17.     public long this[long i]
  18.     {
  19.         get{
  20.             if( i < 0) throw new Exception("");
  21.        
  22.             if(dic.ContainsKey(i) == false)
  23.                 dic.Add(i, 0);
  24.             return dic[i];
  25.         }
  26.         set
  27.         {
  28.             dic[i] = value;
  29.         }
  30.     }
  31.    
  32.     public List<long> inputs;
  33.    
  34.     long adresPointer = 0; 
  35.     int inputPointer = 0;
  36.    
  37.     #region paramaters
  38.     long relModeOffset;
  39.     ParameterMode[] mode = new UserQuery.ParameterMode[3];
  40.     long GetV(int p)
  41.     {
  42.         switch (mode[p - 1])
  43.         {
  44.             case ParameterMode.Immidiat:
  45.                 return this[adresPointer + p];
  46.                
  47.             case ParameterMode.Position:
  48.                 return this[this[adresPointer + p]];
  49.            
  50.             case ParameterMode.Relative:
  51.                 return this[this[adresPointer + p] + relModeOffset];
  52.             default: throw new NotImplementedException();
  53.         }
  54.     }  
  55.  
  56.     public long ParseOpCode(long TotalOpcode)
  57.     {
  58.         mode[2] = (ParameterMode)(TotalOpcode / 10000);
  59.         TotalOpcode %= 10000;
  60.         mode[1] = (ParameterMode)(TotalOpcode / 1000);
  61.         TotalOpcode %= 1000;
  62.         mode[0] = (ParameterMode)(TotalOpcode / 100);
  63.         this.lastOpCode = TotalOpcode % 100;
  64.         return this.lastOpCode;
  65.     }
  66.  
  67.     private void SetValue(long p, long result)
  68.     {
  69.         switch (mode[p - 1])
  70.         {
  71.             case ParameterMode.Immidiat: throw new Exception("Parameters that an instruction writes to will never be in immediate mode.(DAY 05)");
  72.             case ParameterMode.Position: this[this[adresPointer + p]] = result; return;
  73.             case ParameterMode.Relative: this[this[adresPointer + p] + relModeOffset] = result; return;
  74.             default: throw new NotImplementedException();
  75.         }                      
  76.     }
  77.  
  78.     #endregion
  79.     public IntCode(long[] arr, long[] input, bool pauseOnOutput)
  80.     {
  81.         this.dic = arr.Select((x, i) => (x, i)).ToDictionary(x=> (long) x.i, x=> x.x);
  82.         this.inputs = input?.ToList();
  83.         this.cpuID = cpuCount++;
  84.         this.pauseOnOutput = pauseOnOutput;
  85.     }
  86.    
  87.     public void Calculate()
  88.     {  
  89.         while (true)
  90.         {              
  91.             steps++;
  92.             ParseOpCode(this[adresPointer]);
  93.        
  94.             switch (this.lastOpCode)
  95.             {
  96.                 case 1: //ADD
  97.                     ///$"{GetV(1)} + {GetV(2)} => { GetV(1) + GetV(2)}".Dump();
  98.                     SetValue(3, GetV(1) + GetV(2));                
  99.                     adresPointer += 4;
  100.                     break;
  101.                    
  102.                 case 2: //MULT
  103.                     SetValue(3, GetV(1) * GetV(2));                    
  104.                     adresPointer += 4;
  105.                     break;
  106.                    
  107.                 case 3: //GETINPUT
  108.                     SetValue(1, GetInput());                                   
  109.                     adresPointer += 2;
  110.                    
  111.                     break;
  112.                 case 4: //OUTPUT                   
  113.                     Output(GetV(1));                   
  114.                     adresPointer +=2;                  
  115.                     if(pauseOnOutput) return;
  116.                     else break;
  117.                    
  118.                 case 5: //JMP NZ               
  119.                     //Opcode 5 is jump -if-true: if the first parameter is non - zero,
  120.                     //it sets the instruction polonger to the value from the second parameter.Otherwise, it does nothing.
  121.                     if(GetV(1) != 0) adresPointer = GetV(2);
  122.                     else adresPointer += 3;                
  123.                     break;
  124.                    
  125.                 case 6: //JMP Z            
  126.                         //Opcode 6 is jump -if-false: if the first parameter is zero,
  127.                         //it sets the instruction polonger to the value from the second parameter.Otherwise, it does nothing.
  128.                     if (GetV(1) == 0) adresPointer = GetV(2);
  129.                     else              adresPointer += 3;                   
  130.                     break;
  131.  
  132.                 case 7: //LESS THAN
  133.                     //Opcode 7 is less than: if the first parameter is less than the second parameter,
  134.                     //it stores 1 in the position given by the third parameter.Otherwise, it stores 0.
  135.                     if(GetV(1) < GetV(2)) SetValue(3, 1);
  136.                     else                  SetValue(3, 0);                  
  137.                     adresPointer += 4;
  138.                     break;
  139.                    
  140.                 case 8: //EQUAL
  141.                         //Opcode 8 is equals: if the first parameter is equal to the second parameter, it stores 1 in the position given by the third parameter.Otherwise, it stores 0.
  142.                     if (GetV(1) == GetV(2)) SetValue(3, 1);
  143.                     else                    SetValue(3, 0);                
  144.                     adresPointer += 4;                 
  145.                     break;
  146.                
  147.                 case 9: //SET REL                  
  148.                     this.relModeOffset += GetV(1);
  149.                     adresPointer += 2;
  150.                     break;
  151.                
  152.                 case 99:  //DONE
  153.                     if (debug) $"{cpuID} DONE".Dump();
  154.                     return;
  155.                 default: throw new NotImplementedException("Unknown OPCODE");
  156.             }
  157.         }
  158.     }
  159.  
  160.     public long GetInput() => inputs[inputPointer++];  
  161.    
  162.     public long SubmitInput(long i)
  163.     {      
  164.         if(debug) $"{cpuID} RECEIVED {i}".Dump();
  165.         this.inputs.Add(i);
  166.         this.Calculate();
  167.         return this.lastOutput;    
  168.     }
  169.    
  170.     private void Output(long i )
  171.     {
  172.         i.Dump();
  173.         this.lastOutput = i;   
  174.     }  
  175. }
Advertisement
Add Comment
Please, Sign In to add comment