Browse Source

Tidy 18 a little.

master
Chris Smith 6 years ago
parent
commit
57656f0286
1 changed files with 50 additions and 63 deletions
  1. 50
    63
      18.py

+ 50
- 63
18.py View File

@@ -1,36 +1,34 @@
1
+import operator
1 2
 from collections import defaultdict
2 3
 
3
-get_value = lambda registers, operand: registers[operand] if operand in registers else int(operand)
4 4
 
5
-def handle_snd(pc, registers, state, args):
6
-    state['snd'].append(get_value(registers, args[0]))
7
-    state['sndc'] += 1
8
-    return pc + 1
5
+def get_value(registers, operand):
6
+    return registers[operand] if operand in registers else int(operand)
9 7
 
10
-def handle_set(pc, registers, state, args):
11
-    registers[args[0]] = get_value(registers, args[1])
12
-    return pc + 1
13 8
 
14
-def handle_add(pc, registers, state, args):
15
-    registers[args[0]] += get_value(registers, args[1])
16
-    return pc + 1
9
+def handle_generic(op):
10
+    def inner(pc, registers, _, args):
11
+        registers[args[0]] = op(registers[args[0]], get_value(registers, args[1]))
12
+        return pc + 1
13
+    return inner
17 14
 
18
-def handle_mul(pc, registers, state, args):
19
-    registers[args[0]] *= get_value(registers, args[1])
20
-    return pc + 1
21 15
 
22
-def handle_mod(pc, registers, state, args):
23
-    registers[args[0]] %= get_value(registers, args[1])
16
+def handle_snd(pc, registers, state, args):
17
+    state['snd'].append(get_value(registers, args[0]))
18
+    state['sndc'] += 1
24 19
     return pc + 1
25 20
 
26
-def handle_jgz(pc, registers, state, args):
21
+
22
+def handle_jgz(pc, registers, _, args):
27 23
     return pc + get_value(registers, args[1]) if get_value(registers, args[0]) > 0 else pc + 1
28 24
 
25
+
29 26
 def handle_rcv_p1(pc, registers, state, args):
30 27
     if get_value(registers, args[0]) != 0:
31
-        state['recovered'].append(state['snd'][-1])
28
+        state['rcv'].append(state['snd'][-1])
32 29
     return pc + 1
33 30
 
31
+
34 32
 def handle_rcv_p2(pc, registers, state, args):
35 33
     if len(state['rcv']) > 0:
36 34
         registers[args[0]] = state['rcv'].pop(0)
@@ -38,73 +36,62 @@ def handle_rcv_p2(pc, registers, state, args):
38 36
     else:
39 37
         return pc
40 38
 
41
-def process_p1(instructions):
42
-    pc, state, registers = 0, {'snd': [], 'sndc': 0, 'recovered': []}, defaultdict(lambda: 0)
43
-    ops = {
39
+
40
+def get_ops(part_one=True):
41
+    return {
44 42
         'snd': handle_snd,
45
-        'set': handle_set,
46
-        'add': handle_add,
47
-        'mul': handle_mul,
48
-        'mod': handle_mod,
43
+        'set': handle_generic(lambda _, v: v),
44
+        'add': handle_generic(operator.add),
45
+        'mul': handle_generic(operator.mul),
46
+        'mod': handle_generic(operator.mod),
49 47
         'jgz': handle_jgz,
50
-        'rcv': handle_rcv_p1,
48
+        'rcv': handle_rcv_p1 if part_one else handle_rcv_p2
51 49
     }
52
-    while len(state['recovered']) == 0:
53
-        ins = instructions[pc]
54
-        pc = ops[ins[0]](pc, registers, state, ins[1:])
55
-    return state['recovered'][0]
50
+
51
+
52
+def new_program(snd, rcv):
53
+    return {'pc': 0, 'snd': snd, 'sndc': 0, 'rcv': rcv, 'terminated': False, 'waiting': False, 'regs': defaultdict(lambda: 0)}
54
+
55
+
56
+def process_p1(instructions):
57
+    program = new_program([], [])
58
+    ops = get_ops(True)
59
+    while len(program['rcv']) == 0:
60
+        ins = instructions[program['pc']]
61
+        program['pc'] = ops[ins[0]](program['pc'], program['regs'], program, ins[1:])
62
+    return program['rcv'][0]
56 63
 
57 64
 
58 65
 def can_execute(programs):
59
-    for p in programs:
60
-        if p['state']['terminated']:
61
-            yield False
62
-        elif p['state']['waiting'] and len(p['state']['rcv']) == 0:
63
-            yield False
64
-        else:
65
-            yield True
66
+    return any(not p['terminated'] and (not p['waiting'] or len(p['rcv']) > 0) for p in programs)
66 67
 
67 68
 
68 69
 def process_p2(instructions):
69 70
     p1_to_p2, p2_to_p1 = [], []
70
-    programs = [{
71
-        'pc': 0,
72
-        'state': {'snd': p1_to_p2, 'sndc': 0, 'rcv': p2_to_p1, 'terminated': False, 'waiting': False},
73
-        'regs': defaultdict(lambda: 0)
74
-    }, {
75
-        'pc': 0,
76
-        'state': {'snd': p2_to_p1, 'sndc': 0, 'rcv': p1_to_p2, 'terminated': False, 'waiting': False},
77
-        'regs': defaultdict(lambda: 0),
78
-    }]
71
+    programs = [new_program(p1_to_p2, p2_to_p1), new_program(p2_to_p1, p1_to_p2)]
79 72
     programs[1]['regs']['p'] = 1
80 73
 
81
-    ops = {
82
-        'snd': handle_snd,
83
-        'set': handle_set,
84
-        'add': handle_add,
85
-        'mul': handle_mul,
86
-        'mod': handle_mod,
87
-        'jgz': handle_jgz,
88
-        'rcv': handle_rcv_p2,
89
-    }
90
-
74
+    ops = get_ops(False)
91 75
     p = 0
92
-    while any(can_execute(programs)):
76
+    while can_execute(programs):
93 77
         for _ in range(1000):
94 78
             pc = programs[p]['pc']
95
-            programs[p]['state']['waiting'] = False
79
+            programs[p]['waiting'] = False
80
+
96 81
             if pc < 0 or pc >= len(instructions):
97
-                programs[p]['state']['terminated'] = True
82
+                programs[p]['terminated'] = True
98 83
                 break
84
+
99 85
             ins = instructions[pc]
100
-            programs[p]['pc'] = ops[ins[0]](pc, programs[p]['regs'], programs[p]['state'], ins[1:])
86
+            programs[p]['pc'] = ops[ins[0]](pc, programs[p]['regs'], programs[p], ins[1:])
87
+
101 88
             if programs[p]['pc'] == pc:
102
-                programs[p]['state']['waiting'] = True
89
+                programs[p]['waiting'] = True
103 90
                 break
104
-        p = 1 - p
105 91
 
106
-    return programs[1]['state']['sndc']
92
+        p = 1 - p
107 93
 
94
+    return programs[1]['sndc']
108 95
 
109 96
 
110 97
 with open('data/18.txt', 'r') as file:

Loading…
Cancel
Save