about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Day7.cs73
-rw-r--r--aoc2019.csproj3
-rw-r--r--input/day7.in1
-rw-r--r--lib/Extensions.cs15
-rw-r--r--lib/IntCodeVM.cs94
5 files changed, 186 insertions, 0 deletions
diff --git a/Day7.cs b/Day7.cs
new file mode 100644
index 0000000..63f5855
--- /dev/null
+++ b/Day7.cs
@@ -0,0 +1,73 @@
+using aoc2019.lib;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace aoc2019
+{
+    internal class Day7 : Day
+    {
+        public override int DayNumber => 7;
+
+        private readonly List<int> input;
+        private readonly IntCodeVM[] Amplifiers = new IntCodeVM[5];
+        public Day7()
+        {
+            input = Input.First().Split(',').Select(int.Parse).ToList();
+            for (var i = 0; i < 5; i++) Amplifiers[i] = new IntCodeVM(input);
+        }
+
+        
+
+        public override string Part1()
+        {
+            int i, largest = 0;
+
+            foreach (var phaseSeq in Enumerable.Range(0, 5).Permute())
+            {
+                i = 0;
+                foreach (var (vm, phase) in Amplifiers.Zip(phaseSeq))
+                {
+                    vm.Reset();
+                    vm.Run(phase, i);
+                    i = vm.Result;
+                }
+
+                if (i > largest)
+                    largest = i;
+            }
+
+            return $"{largest}";
+        }
+
+        public override string Part2()
+        {
+            int i, largest = 0;
+
+            foreach (var phaseSeq in Enumerable.Range(5, 5).Permute())
+            {
+                i = 0;
+                foreach (var (vm, phase) in Amplifiers.Zip(phaseSeq))
+                {
+                    vm.Reset();
+                    vm.input.Enqueue(phase);
+                }
+
+                var vms = new Queue<IntCodeVM>(Amplifiers);
+                while (vms.Count > 0)
+                {
+                    var vm = vms.Dequeue();
+                    var haltType = vm.Run(i);
+                    if (haltType == IntCodeVM.HaltType.Waiting)
+                        vms.Enqueue(vm);
+                    i = vm.Result;
+                }
+
+                if (i > largest)
+                    largest = i;
+            }
+
+            return $"{largest}";
+        }
+    }
+}
diff --git a/aoc2019.csproj b/aoc2019.csproj
index b777405..d98bb99 100644
--- a/aoc2019.csproj
+++ b/aoc2019.csproj
@@ -24,6 +24,9 @@
     <None Update="input\day6.in">

       <CopyToOutputDirectory>Always</CopyToOutputDirectory>

     </None>

+    <None Update="input\day7.in">

+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>

+    </None>

   </ItemGroup>

 

 </Project>

diff --git a/input/day7.in b/input/day7.in
new file mode 100644
index 0000000..0128ef0
--- /dev/null
+++ b/input/day7.in
@@ -0,0 +1 @@
+3,8,1001,8,10,8,105,1,0,0,21,46,59,84,93,110,191,272,353,434,99999,3,9,101,2,9,9,102,3,9,9,1001,9,5,9,102,4,9,9,1001,9,4,9,4,9,99,3,9,101,3,9,9,102,5,9,9,4,9,99,3,9,1001,9,4,9,1002,9,2,9,101,2,9,9,102,2,9,9,1001,9,3,9,4,9,99,3,9,1002,9,2,9,4,9,99,3,9,102,2,9,9,1001,9,5,9,1002,9,3,9,4,9,99,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,99,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,99,3,9,101,1,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,99,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,99,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,99
\ No newline at end of file
diff --git a/lib/Extensions.cs b/lib/Extensions.cs
new file mode 100644
index 0000000..52863d0
--- /dev/null
+++ b/lib/Extensions.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace aoc2019.lib
+{
+    public static class Extensions
+    {
+        public static IEnumerable<IEnumerable<T>> Permute<T>(this IEnumerable<T> list)
+        {
+            if (list.Count() == 1) return new[] { list };
+            return list.SelectMany(t => Permute(list.Where(x => !x.Equals(t))), (v, p) => p.Prepend(v));
+        }
+    }
+}
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;
+        }
+    }
+}