-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpuzzle13.py
118 lines (112 loc) · 4.69 KB
/
puzzle13.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
from puzzle09 import load_addr, load_param, write, is_valid
def run(input_program, input_values):
program = input_program[:]
index = 0
relative_base = 0
extra_mem = {}
prints = []
while True:
instruction = program[index]
op_str = f"{instruction:05}" # pad with zeros if necessary
op = op_str[-2:]
mode_param3, mode_param2, mode_param1 = op_str[0], op_str[1], op_str[2]
jump = False
# add
if op == '01':
nincrement = 4
param1 = load_param(program, index + 1, mode_param1, extra_mem, relative_base)
param2 = load_param(program, index + 2, mode_param2, extra_mem, relative_base)
write_addr = load_addr(program, index + 3, mode_param3, relative_base)
write(program, write_addr, param1 + param2, extra_mem)
index += nincrement
# multiply
elif op == '02':
nincrement = 4
param1 = load_param(program, index + 1, mode_param1, extra_mem, relative_base)
param2 = load_param(program, index + 2, mode_param2, extra_mem, relative_base)
write_addr = load_addr(program, index + 3, mode_param3, relative_base)
write(program, write_addr, param1 * param2, extra_mem)
index += nincrement
# input_value written to address
elif op == '03':
nincrement = 2
write_addr = load_addr(program, index + 1, mode_param1, relative_base)
if len(input_values) > 0:
input_value = input_values.pop(0)
write(program, write_addr, input_value, extra_mem)
index += nincrement
else:
return program, prints, False # not finished
# output parameter
elif op == '04':
nincrement = 2
addr = load_addr(program, index + 1, mode_param1, relative_base)
if is_valid(addr, program):
prints.append(program[addr])
elif addr in extra_mem:
prints.append(extra_mem[addr])
else:
raise ValueError
index += nincrement
# jump if true
elif op == '05':
param1 = load_param(program, index + 1, mode_param1, extra_mem, relative_base)
param2 = load_param(program, index + 2, mode_param2, extra_mem, relative_base)
if param1 != 0:
index = param2
else:
nincrement = 3
index += nincrement
# jump if false
elif op == '06':
param1 = load_param(program, index + 1, mode_param1, extra_mem, relative_base)
param2 = load_param(program, index + 2, mode_param2, extra_mem, relative_base)
if param1 == 0:
index = param2
else:
nincrement = 3
index += nincrement
# less than
elif op == '07':
nincrement = 4
param1 = load_param(program, index + 1, mode_param1, extra_mem, relative_base)
param2 = load_param(program, index + 2, mode_param2, extra_mem, relative_base)
write_addr = load_addr(program, index + 3, mode_param3, relative_base)
if param1 < param2: # strict?
write(program, write_addr, 1, extra_mem)
else:
write(program, write_addr, 0, extra_mem)
index += nincrement
# equals
elif op == '08':
nincrement = 4
param1 = load_param(program, index + 1, mode_param1, extra_mem, relative_base)
param2 = load_param(program, index + 2, mode_param2, extra_mem, relative_base)
write_addr = load_addr(program, index + 3, mode_param3, relative_base)
if param1 == param2:
write(program, write_addr, 1, extra_mem)
else:
write(program, write_addr, 0, extra_mem)
index += nincrement
# adjust relative base
elif op == '09':
param1 = load_param(program, index + 1, mode_param1, extra_mem, relative_base)
relative_base += param1
index += 2
# end program
elif op == '99':
return program, prints, True
else:
raise NotImplementedError()
def prints2screen(prints):
screen = dict()
for x, y, tile_id in zip(prints[::3], prints[1::3], prints[2::3]):
if x >= 0:
pixel = x - 1j * y
screen[pixel] = tile_id
return screen
# part1
program = list(map(int, open('data/input13').read().split(',')))
state, prints, is_finished = run(program, input_values=[])
screen = prints2screen(prints)
print(f"solution for part1: {sum([1 for val in screen.values() if val == 2])}")