aoc

commit 09c117f3ca684a40adbc2c3c9255e8c1214ed429

Author: Honza Pokorny <me@honza.ca>

7p2

 007/main.py | 81 ++++++++++++++++++++++++++++++++++++++----------------


diff --git a/007/main.py b/007/main.py
index 97d373b878212f1cf602b920f1c5f30fce796f5f..8372b7d4ea77ed2c0a6ed13fc0a04c6ba7596020 100644
--- a/007/main.py
+++ b/007/main.py
@@ -5,6 +5,8 @@
 opcode = re.compile(r'(\d{2})')
 
 OPS = ['01', '02', '03', '04', '99']
+NEEDS_INPUT = 'NI'
+HALT = 'H'
 
 
 def rev(s):
@@ -29,13 +31,12 @@ def mult(a, b):
     return a * b
 
 
-def intcode(input_list, *input_codes):
+def intcode(input_list, *input_codes, cur=0):
     input_codes = list(input_codes)
     input_codes.reverse()
 
     outputs = []
 
-    cur = 0
     # if input_list[0] == 3:
     #     input_list[input_list[1]] = input_codes.pop()
     #     cur += 2
@@ -95,6 +96,15 @@             cur += 4
             continue
 
         if op == '03':
+
+            if not input_codes:
+                return {
+                    'output': outputs,
+                    'state': NEEDS_INPUT,
+                    'memory': input_list,
+                    'cur': cur,
+                }
+
             input_list[input_list[cur + 1]] = input_codes.pop()
             cur += 2
             continue
@@ -193,30 +203,56 @@
             cur += 4
             continue
 
-    return outputs
+    return {
+        'output': outputs,
+        'state': HALT,
+        'memory': input_list,
+        'cur': None
+    }
 
 
 def run_phases(input_list, phases):
     prog_input = 0
+    cur = 0
 
-    for phase in phases:
-        out = intcode(input_list, phase, prog_input)
+    state = {}
+
+    while True:
+        for p in itertools.repeat(phases):
+            for i in phases:
+                amplifier_state = state.get(i, {
+                    'memory': copy.deepcopy(input_list),
+                    'cur': 0,
+                    'state': None
+                })
+
+                if not amplifier_state['state']:
+                    inputs = [i, prog_input]
+                else:
+                    inputs = [prog_input]
+
+                out = intcode(amplifier_state['memory'],
+                              *inputs,
+                              cur=amplifier_state['cur'])
 
-        if not len(out):
-            raise Exception('no out')
+                if out['state'] == HALT:
+                    if i == phases[-1]:
+                        return out['output'][0]
 
-        prog_input = out[0]
+                state[i] = out
+                prog_input = out['output'][0]
 
-    return prog_input
+                if prog_input > 1000000000000:
+                    raise Exception('too much')
 
 
 def find_solution(input_list):
     max_v = 0
     max_perm = None
 
-    for v in itertools.permutations('01234'):
+    for v in itertools.permutations('56789'):
         phases = list(map(int, list(v)))
-        prog_out = run_phases(input_list, phases)
+        prog_out = run_phases(copy.deepcopy(input_list), phases)
 
         if prog_out > max_v:
             max_v = prog_out
@@ -232,22 +268,20 @@
 def main():
     inputs = [
         (
-           [3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0],
-            [4,3,2,1,0],
-            43210
+           [3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26, 27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5],
+           [9,8,7,6,5],
+           139629729
         ),
 
         (
-            [3,23,3,24,1002,24,10,24,1002,23,-1,23, 101,5,23,23,1,24,23,23,4,23,99,0,0],
-            [0,1,2,3,4],
-            54321
+            [
+                3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54,
+                -5,54,1105,1,12,1,53,54,53,1008,54,0,55,1001,55,1,55,2,53,55,53,4,
+                53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10
+            ],
+            [9,7,8,5,6],
+            18216
         ),
-
-        (
-            [3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0],
-            [1,0,4,3,2],
-            65210
-        )
 
     ]
 
@@ -260,7 +294,6 @@     #     actual_phase, actual_value = find_solution(input_list)
     #     print(actual_phase, expected_phase)
     #     print(actual_value, expected_value)
     #     print('')
-
     print(find_solution(puzzle_input))
 
 if __name__ == '__main__':