about summary refs log tree commit diff
path: root/lib/IntCodeVM.cs
diff options
context:
space:
mode:
authorBen Harris <ben@tilde.team>2019-12-07 03:57:17 -0500
committerBen Harris <ben@tilde.team>2019-12-07 03:57:17 -0500
commit9dcee6f61d0c856fd9c334445db6ca030a5a6403 (patch)
tree9a7ac3bd7fdb2ddab8244eefd41828ba65c27657 /lib/IntCodeVM.cs
parent5759cac12d42e92d7f07aa54d4bf376f2e63995b (diff)
day 7
Diffstat (limited to 'lib/IntCodeVM.cs')
-rw-r--r--lib/IntCodeVM.cs94
1 files changed, 94 insertions, 0 deletions
diff --git a/lib/IntCodeVM.cs b/lib/IntCodeVM.cs
new file mode 100644
index 0000000..de2b98a
--- /dev/null
+++ b/lib/IntCodeVM.cs
@@ -0,0 +1,94 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace aoc2019.lib
+{
+    public class IntCodeVM
+    {
+        private int i;
+        public List<int> v;
+        public Queue<int> input, output;
+        private readonly List<int> program;
+
+        public IntCodeVM(List<int> tape)
+        {
+            i = 0;
+            program = tape;
+            v = tape;
+            input = new Queue<int>();
+            output = new Queue<int>();
+        }
+
+        public enum HaltType
+        {
+            Terminate,
+            Waiting
+        }
+
+        enum Op : int
+        {
+            ADD = 1, MUL = 2, INPUT = 3, OUTPUT = 4, JMP = 5, JNE = 6, LT = 7, EQ = 8, HALT = 99
+        }
+
+        public void Reset()
+        {
+            i = 0;
+            v = program;
+            input.Clear();
+            output.Clear();
+        }
+
+        public int Result => output.Dequeue();
+
+        public HaltType Run(params int[] additionalInput)
+        {
+            foreach (var i in additionalInput) input.Enqueue(i);
+            return Run();
+        }
+        public HaltType Run()
+        {
+            while (i < v.Count)
+            {
+                int Val(int mode, int val) =>
+                    mode == 0 ? v[val] : val;
+
+                int Val1() => Val(v[i] / 100 % 10, v[i + 1]);
+                int Val2() => Val(v[i] / 1000, v[i + 2]);
+
+                switch ((Op)(v[i] % 100))
+                {
+                    case Op.ADD:
+                        v[v[i + 3]] = Val1() + Val2();
+                        i += 4; break;
+                    case Op.MUL:
+                        v[v[i + 3]] = Val1() * Val2();
+                        i += 4; break;
+                    case Op.INPUT:
+                        if (!input.Any())
+                            return HaltType.Waiting;
+                        v[v[i + 1]] = input.Dequeue();
+                        i += 2; break;
+                    case Op.OUTPUT:
+                        output.Enqueue(Val1());
+                        i += 2; break;
+                    case Op.JMP:
+                        i = Val1() == 0 ? i + 3 : Val2();
+                        break;
+                    case Op.JNE:
+                        i = Val1() != 0 ? i + 3 : Val2();
+                        break;
+                    case Op.LT:
+                        v[v[i + 3]] = Val1() < Val2() ? 1 : 0;
+                        i += 4; break;
+                    case Op.EQ:
+                        v[v[i + 3]] = Val1() == Val2() ? 1 : 0;
+                        i += 4; break;
+                    case Op.HALT:
+                        return HaltType.Terminate;
+                }
+            }
+
+            return HaltType.Terminate;
+        }
+    }
+}