···11import fileinput
2233-44-# True = read, False = write
55-INSTRUCTIONS = {
66- 1: (True, True, False),
77- 2: (True, True, False),
88- 3: (False, None, None),
99- 4: (True, None, None),
1010- 5: (True, True, None),
1111- 6: (True, True, None),
1212- 7: (True, True, False),
1313- 8: (True, True, False),
1414- 9: (True, None, None),
1515- 99: (None, None, None)
1616-}
1717-1818-1919-GLOBAL_INPUTS = [0]
2020-2121-2222-def parse_mode(tape, mode_op, a, b, c):
2323- op = mode_op % 100
2424- mode_a = (mode_op // 100) % 10
2525- mode_b = (mode_op // 1000) % 10
2626- mode_c = (mode_op // 10000) % 10
2727-2828- return op, mode_a, mode_b, mode_c
2929-3030-3131-def emulate(pid, pc=0):
3232- tape = TAPE[:]
3333- outs = []
3434- relative_base = 0
3535-3636- def resolve_modes(op, params, modes):
3737- res = [a, b, c]
3838-3939- for i, (is_read, p, m) in enumerate(zip(INSTRUCTIONS[op], params, modes)):
4040- if is_read is None:
4141- continue
4242-4343- if is_read:
4444- if m == 0:
4545- res[i] = tape[p]
4646- elif m == 1:
4747- res[i] = p
4848- elif m == 2:
4949- res[i] = tape[relative_base + p]
5050- else:
5151- if m == 0:
5252- res[i] = p
5353- elif m == 2:
5454- res[i] = relative_base + p
5555-5656- return res
5757-5858- while pc < len(tape):
5959- mode_op, a, b, c = tape[pc:pc+4]
6060- op, mode_a, mode_b, mode_c = parse_mode(tape, mode_op, a, b, c)
6161- a, b, c = resolve_modes(op, (a, b, c), (mode_a, mode_b, mode_c))
6262-6363- # ADD a b c
6464- if op == 1:
6565- tape[c] = a + b
6666- pc += 4
6767-6868- # MUL a b c
6969- elif op == 2:
7070- tape[c] = a * b
7171- pc += 4
7272-7373- # INP a
7474- elif op == 3:
7575- tape[a] = GLOBAL_INPUTS[pid]
7676- pc += 2
7777-7878- # OUT b
7979- elif op == 4:
8080- outs.append(a)
8181- pc += 2
8282-8383- # JZ a b
8484- elif op == 5:
8585- if a != 0:
8686- pc = b
8787- else:
8888- pc += 3
8989-9090- # JNZ a b
9191- elif op == 6:
9292- if a == 0:
9393- pc = b
9494- else:
9595- pc += 3
9696-9797- # LT a b c
9898- elif op == 7:
9999- tape[c] = 1 if a < b else 0
100100- pc += 4
101101-102102- # EQ a b c
103103- elif op == 8:
104104- tape[c] = 1 if a == b else 0
105105- pc += 4
106106-107107- elif op == 9:
108108- relative_base += a
109109- pc += 2
110110-111111- # HALT
112112- elif op == 99:
113113- return outs
33+from intcode import emulate
11441155# Read input
1166TAPE = [int(x) for x in fileinput.input()[0].split(',')]
1177TAPE += [0] * 100000 # Pad memory
1188119119-GLOBAL_INPUTS[0] = 1
120120-print "BOOST keycode:", emulate(0)[0]
121121-122122-GLOBAL_INPUTS[0] = 2
123123-print "Coordinates of distress signal:", emulate(0)[0]
99+print "BOOST keycode:", next(emulate(TAPE, [1]))
1010+print "Coordinates of distress signal:", next(emulate(TAPE, [2]))
+7-116
2019/day11.py
···22import fileinput
33from collections import defaultdict
4455-66-GLOBAL_INPUTS = [0]
77-88-# True = read, False = write
99-INSTRUCTIONS = {
1010- 1: ('ADD', (True, True, False)),
1111- 2: ('MUL', (True, True, False)),
1212- 3: ('INP', (False, None, None)),
1313- 4: ('OUT', (True, None, None)),
1414- 5: ('JZ ', (True, True, None)),
1515- 6: ('JNZ', (True, True, None)),
1616- 7: ('LT ', (True, True, False)),
1717- 8: ('EQ ', (True, True, False)),
1818- 9: ('REL', (True, None, None)),
1919- 99: ('HLT', (None, None, None)),
2020-}
2121-2222-2323-def parse_mode(tape, mode_op, a, b, c):
2424- op = mode_op % 100
2525- mode_a = (mode_op // 100) % 10
2626- mode_b = (mode_op // 1000) % 10
2727- mode_c = (mode_op // 10000) % 10
2828-2929- return op, mode_a, mode_b, mode_c
3030-3131-3232-def emulate(pid, pc=0):
3333- tape = TAPE[:]
3434- outs = []
3535- relative_base = 0
55+from intcode import emulate
3663737- def resolve_modes(op, params, modes):
3838- res = [a, b, c]
3974040- for i, (is_read, p, m) in enumerate(zip(INSTRUCTIONS[op][1], params, modes)):
4141- if is_read is None:
4242- continue
4343-4444- if is_read:
4545- if m == 0:
4646- res[i] = tape[p]
4747- elif m == 1:
4848- res[i] = p
4949- elif m == 2:
5050- res[i] = tape[relative_base + p]
5151- else:
5252- if m == 0:
5353- res[i] = p
5454- elif m == 2:
5555- res[i] = relative_base + p
5656-5757- return res
5858-5959- while pc < len(tape):
6060- mode_op, a, b, c = tape[pc:pc+4]
6161- op, mode_a, mode_b, mode_c = parse_mode(tape, mode_op, a, b, c)
6262- a, b, c = resolve_modes(op, (a, b, c), (mode_a, mode_b, mode_c))
6363-6464- # ADD a b c
6565- if op == 1:
6666- tape[c] = a + b
6767- pc += 4
6868-6969- # MUL a b c
7070- elif op == 2:
7171- tape[c] = a * b
7272- pc += 4
7373-7474- # INP a
7575- elif op == 3:
7676- tape[a] = GLOBAL_INPUTS[pid]
7777- pc += 2
7878-7979- # OUT b
8080- elif op == 4:
8181- yield a
8282- pc += 2
8383-8484- # JZ a b
8585- elif op == 5:
8686- if a != 0:
8787- pc = b
8888- else:
8989- pc += 3
9090-9191- # JNZ a b
9292- elif op == 6:
9393- if a == 0:
9494- pc = b
9595- else:
9696- pc += 3
9797-9898- # LT a b c
9999- elif op == 7:
100100- tape[c] = 1 if a < b else 0
101101- pc += 4
102102-103103- # EQ a b c
104104- elif op == 8:
105105- tape[c] = 1 if a == b else 0
106106- pc += 4
107107-108108- elif op == 9:
109109- relative_base += a
110110- pc += 2
111111-112112- # HALT
113113- elif op == 99:
114114- raise StopIteration()
115115-116116-117117-def simulate_robot(start=0):
88+def simulate_robot(tape, start=0):
1189 grid = {}
11910 grid[0, 0] = start
1201112112 facing = 0
12213 x, y = 0, 0
12314124124- robot = emulate(0)
1515+ inputs = [start]
1616+ robot = emulate(tape[:], inputs)
1251712618 try:
12719 while True:
···14032 elif facing == 3:
14133 x -= 1
14234143143- GLOBAL_INPUTS[0] = grid.get((x, y), 0)
3535+ inputs[0] = grid.get((x, y), 0)
14436 except StopIteration:
14537 return grid
14638···14941TAPE = [int(x) for x in fileinput.input()[0].split(',')]
15042TAPE += [0] * 100000
15143152152-15344# Part 1
154154-grid = simulate_robot(0)
4545+grid = simulate_robot(TAPE, 0)
15546print "Number of painted tiles:", len(grid.keys())
156471574815849# Part 2
159159-grid = simulate_robot(1)
5050+grid = simulate_robot(TAPE, 1)
1605116152print "Registration ID:\n"
16253xs, ys = zip(*grid.keys())
+6-114
2019/day13.py
···11import fileinput
22from collections import Counter
3344-55-GLOBAL_INPUTS = [0]
66-77-88-# True = read, False = write
99-INSTRUCTIONS = {
1010- 1: ('ADD', (True, True, False)),
1111- 2: ('MUL', (True, True, False)),
1212- 3: ('INP', (False, None, None)),
1313- 4: ('OUT', (True, None, None)),
1414- 5: ('JZ ', (True, True, None)),
1515- 6: ('JNZ', (True, True, None)),
1616- 7: ('LT ', (True, True, False)),
1717- 8: ('EQ ', (True, True, False)),
1818- 9: ('REL', (True, None, None)),
1919- 99: ('HLT', (None, None, None)),
2020-}
2121-2222-2323-def parse_mode(tape, mode_op, a, b, c):
2424- op = mode_op % 100
2525- mode_a = (mode_op // 100) % 10
2626- mode_b = (mode_op // 1000) % 10
2727- mode_c = (mode_op // 10000) % 10
2828-2929- return op, mode_a, mode_b, mode_c
3030-3131-3232-def emulate(pid, pc=0):
3333- tape = TAPE[:]
3434- relative_base = 0
3535-3636- def resolve_modes(op, params, modes):
3737- res = [a, b, c]
3838-3939- for i, (is_read, p, m) in enumerate(zip(INSTRUCTIONS[op][1], params, modes)):
4040- if is_read is None:
4141- continue
4242-4343- if is_read:
4444- if m == 0:
4545- res[i] = tape[p]
4646- elif m == 1:
4747- res[i] = p
4848- elif m == 2:
4949- res[i] = tape[relative_base + p]
5050- else:
5151- if m == 0:
5252- res[i] = p
5353- elif m == 2:
5454- res[i] = relative_base + p
5555-5656- return res
5757-5858- while pc < len(tape):
5959- mode_op, a, b, c = tape[pc:pc+4]
6060- op, mode_a, mode_b, mode_c = parse_mode(tape, mode_op, a, b, c)
6161- a, b, c = resolve_modes(op, (a, b, c), (mode_a, mode_b, mode_c))
6262-6363- # ADD a b c
6464- if op == 1:
6565- tape[c] = a + b
6666- pc += 4
6767-6868- # MUL a b c
6969- elif op == 2:
7070- tape[c] = a * b
7171- pc += 4
7272-7373- # INP a
7474- elif op == 3:
7575- tape[a] = GLOBAL_INPUTS[pid]
7676- pc += 2
7777-7878- # OUT b
7979- elif op == 4:
8080- yield a
8181- pc += 2
8282-8383- # JZ a b
8484- elif op == 5:
8585- if a != 0:
8686- pc = b
8787- else:
8888- pc += 3
8989-9090- # JNZ a b
9191- elif op == 6:
9292- if a == 0:
9393- pc = b
9494- else:
9595- pc += 3
9696-9797- # LT a b c
9898- elif op == 7:
9999- tape[c] = 1 if a < b else 0
100100- pc += 4
101101-102102- # EQ a b c
103103- elif op == 8:
104104- tape[c] = 1 if a == b else 0
105105- pc += 4
106106-107107- elif op == 9:
108108- relative_base += a
109109- pc += 2
110110-111111- # HALT
112112- elif op == 99:
113113- raise StopIteration()
44+from intcode import emulate
114511561167# Read input
···1189TAPE += [0] * 100000
11910TAPE[0] = 2
12011121121-game = emulate(0)
1212+inputs = [0]
1313+game = emulate(TAPE, inputs)
12214grid = {}
12315ball_x = 0
12416padd_x = 0
···14335 ball_x = x
1443614537 if ball_x < padd_x:
146146- GLOBAL_INPUTS[0] = -1
3838+ inputs[0] = -1
14739 elif ball_x > padd_x:
148148- GLOBAL_INPUTS[0] = 1
4040+ inputs[0] = 1
14941 else:
150150- GLOBAL_INPUTS[0] = 0
4242+ inputs[0] = 0
1514315244except StopIteration:
15345 print "Score after last block is broken:", score
+7-7
2019/day15.py
···2121}
222223232424-def robot_dfs(vm, graph, curr, approach_d):
2424+def robot_dfs(vm, instructions, graph, curr, approach_d):
2525 for d in range(4):
2626 np = curr + ROBOT_DIRS[d]
2727 if np in graph:
2828 continue
29293030 # Attempt to move to next tile
3131- GLOBAL_INPUTS[0] = d + 1
3131+ instructions[0] = d + 1
3232 resp = next(vm)
33333434 if resp == 0:
···3838 global OXYGEN
3939 OXYGEN = np
4040 BOARD[np] = resp
4141- robot_dfs(vm, graph, np, d)
4141+ robot_dfs(vm, instructions, graph, np, d)
42424343 # Can't rely on call stack alone to backtrack
4444- GLOBAL_INPUTS[0] = INVERSE_DIRS[approach_d] + 1
4444+ instructions[0] = INVERSE_DIRS[approach_d] + 1
4545 next(vm)
46464747···7474TAPE = [int(x) for x in fileinput.input()[0].split(',')]
7575TAPE += [0] * 100000
76767777-GLOBAL_INPUTS = [0]
7877BOARD = {}
7978OXYGEN = None
80798181-vm = emulate(TAPE, 0, GLOBAL_INPUTS)
8282-robot_dfs(vm, BOARD, Point(0, 0), 0)
8080+instructions = [0]
8181+vm = emulate(TAPE, instructions)
8282+robot_dfs(vm, instructions, BOARD, Point(0, 0), 0)
83838484print "Optimal movement to oxygen:", bfs(BOARD, Point(0, 0), OXYGEN)
8585print "Minutes taken to fill up:", bfs(BOARD, OXYGEN) - 1
+2-2
2019/day17.py
···101011111212# Part 1
1313-vm = emulate(TAPE[:], 0, [])
1313+vm = emulate(TAPE[:], [])
1414board = []
15151616try:
···6161 instructions.append(ord('\n'))
62626363TAPE[0] = 2
6464-for c in emulate(TAPE[:], 0, instructions, seq_input=True):
6464+for c in emulate(TAPE[:], instructions):
6565 try:
6666 print chr(c),
6767 except Exception:
+1-1
2019/day19.py
···1010 if x < 0 or y < 0:
1111 return 0
12121313- vm = emulate(TAPE, 0, [x, y], seq_input=True)
1313+ vm = emulate(TAPE, [x, y])
1414 return next(vm)
15151616
+37-7
2019/intcode.py
···11+from collections import defaultdict
22+33+# Potential debug output
44+BREAKPOINTS = set([])
55+LAST_SEEN = defaultdict(list)
66+17# True = read, False = write
28INSTRUCTIONS = {
39 1: ('ADD', (True, True, False)),
···1319}
142015212222+def debug_param_mode(param, mode, relative_base):
2323+ if mode == 0:
2424+ return '%({})'.format(param)
2525+ elif mode == 1:
2626+ return str(param)
2727+ elif mode == 2:
2828+ return '%({}{}{})'.format(relative_base, '+' if param >= 0 else '', param)
2929+3030+1631def parse_mode(tape, mode_op, a, b, c):
1732 op = mode_op % 100
1833 mode_a = (mode_op // 100) % 10
···2237 return op, mode_a, mode_b, mode_c
233824392525-def emulate(tape, pid, inputs, pc=0, seq_input=True):
4040+def emulate(tape, inputs, pc=0, relative_base=0, debug=False):
2641 tape = tape[:]
2727- relative_base = 0
2842 ipc = 0
29433044 def resolve_modes(op, params, modes):
···5266 while pc < len(tape):
5367 mode_op, a, b, c = tape[pc:pc+4]
5468 op, mode_a, mode_b, mode_c = parse_mode(tape, mode_op, a, b, c)
6969+ modes = [mode_a, mode_b, mode_c]
7070+ last_pc = pc
7171+7272+ if debug:
7373+ foo = INSTRUCTIONS.get(op, ('???', ()))
7474+ ins = foo[0]
7575+ n = sum(i is not None for i in foo[1])
7676+ params = ' '.join(debug_param_mode(tape[pc+1+i], modes[i], relative_base) for i in range(n))
7777+ print 'PC: {:3} RB: {:3} |'.format(pc, relative_base), ins, params
7878+7979+ if pc in BREAKPOINTS:
8080+ if pc in LAST_SEEN:
8181+ for i, (m, n) in enumerate(zip(LAST_SEEN[pc], tape)):
8282+ if m != n:
8383+ print " | > {}: {} -> {}".format(i, m, n)
8484+8585+ LAST_SEEN[last_pc] = tape[:]
8686+ time.sleep(0.001)
8787+5588 a, b, c = resolve_modes(op, (a, b, c), (mode_a, mode_b, mode_c))
56895790 # ADD a b c
···669967100 # INP a
68101 elif op == 3:
6969- if seq_input:
7070- tape[a] = inputs[ipc % len(inputs)]
7171- ipc += 1
7272- else:
7373- tape[a] = inputs[pid]
102102+ tape[a] = inputs[ipc % len(inputs)]
103103+ ipc += 1
74104 pc += 2
7510576106 # OUT b