def readfile(path):
with open(path) as input_file:
return input_file.read().strip()
def params(program, i, count):
modes = str(program[i] // 100)[::-1]
result = []
for x in range(count - 1):
arg = program[i + 1 + x]
if x >= len(modes) or modes[x] == "0":
result.append(program[arg])
elif modes[x] == "2":
result.append(program[program.offset + arg])
else:
result.append(arg)
output = program[i + count]
if len(modes) >= count and modes[count - 1] == "2":
output += program.offset
result.append(output) # output
return result
def add(program, i, **kwargs):
assert program[i] % 100 == 1
a, b, out = params(program, i, 3)
program[out] = a + b
return i + 4, None
def mul(program, i, **kwargs):
assert program[i] % 100 == 2
a, b, out = params(program, i, 3)
program[out] = a * b
return i + 4, None
def inp(program, i, input_value, **kwargs):
assert program[i] % 100 == 3
out, = params(program, i, 1)
program[out] = input_value
# print(f"> {program[i]} program[{out}] = {program[out]}")
return i + 2, None
def out(program, i, **kwargs):
assert program[i] % 100 == 4
val, _ = params(program, i, 2)
# print(f"> {val}")
return i + 2, val
def jit(program, i, **kwargs):
assert program[i] % 100 == 5
test, ip, _ = params(program, i, 3)
if test != 0:
return ip, None
return i + 3, None
def jif(program, i, **kwargs):
assert program[i] % 100 == 6
test, ip, _ = params(program, i, 3)
if test == 0:
return ip, None
return i + 3, None
def lt(program, i, **kwargs):
assert program[i] % 100 == 7
a, b, out = params(program, i, 3)
program[out] = int(a < b)
return i + 4, None
def eq(program, i, **kwargs):
assert program[i] % 100 == 8
a, b, out = params(program, i, 3)
program[out] = int(a == b)
return i + 4, None
def rbo(program, i, **kwargs):
assert program[i] % 100 == 9
delta, _ = params(program, i, 2)
program.offset += delta
# print (f"> rbo = {program.offset}" )
return i + 2, None
operations = { 1: add, 2: mul, 3: inp, 4: out, 5: jit, 6: jif, 7: lt, 8: eq, 9: rbo }
class Program(list):
def __init__(self, *args, **kwargs):
super(Program, self).__init__(args[0])
self.offset = 0
def compute(program, debug=False):
program = Program(program)
l = len(program)
i = 0
output_value = None
last_output = None
while i < l:
op = program[i]
if op == 99:
if debug:
print(f">> exit {output_value}")
return
if debug:
print(f">> {i}, {list(enumerate(program))[i:i+5]}")
if op % 100 == 3:
input_value = yield
else:
input_value = None
i, output_value = operations[op % 100](program, i, input_value=input_value)
if output_value is not None:
yield output_value
raise Exception("Didn't terminate properly")
def process(listing):
lst = list(map(int, listing.split(",")))
lst.extend([0] * 100000)
return lst
output = list(compute(process(readfile("AoC/input13.txt"))))
def create_screen(output):
screen = {}
i = 0
while i < len(output):
x = output[i]
y = output[i + 1]
tileid = output[i + 2]
screen[(x, y)] = tileid
i += 3
return screen
counter = 0
for coord, val in create_screen(output).items():
if val == 2:
counter += 1
counter
def start_game():
listing = process(readfile("AoC/input13.txt"))
listing[0] = 2
return compute(listing)
def print_screen(screen):
maxx = max(map(lambda x: x[0], screen.keys())) + 1
maxy = max(map(lambda x: x[1], screen.keys())) + 1
for y in range(maxy):
for x in range(maxx):
tileid = screen.get((x, y), 0)
if tileid == 0:
print(' ', end='')
if tileid == 1:
print('|', end='')
elif tileid == 2:
print('#', end='')
elif tileid == 3:
print('-', end='')
elif tileid == 4:
print('o', end='')
print()
print()
def play():
game = start_game()
screen = {}
last_x = True
score = None
ball_xs = []
ball_y = None
slider = None
slider_y = None
counter = 0
last_print = 0
try:
while True:
counter += 1
if last_x is not None:
x = next(game)
else:
step = 0
if len(ball_xs) >= 2 and not (slider_y - 1 == ball_y and ball_xs[-1] == slider):
vx = ball_xs[-1] - ball_xs[-2]
ball_next_x = ball_xs[-1] + vx
if ball_next_x > slider:
step = 1
elif ball_next_x < slider:
step = -1
x = game.send(step)
if x == -1:
assert next(game) == 0
score = next(game)
elif x is not None:
y = next(game)
tileid = next(game)
screen[(x, y)] = tileid
if tileid == 4:
ball_xs.append(x)
ball_y = y
elif tileid == 3:
slider = x
slider_y = y
else:
if counter - last_print >= 1000:
print(f"Score: {score}")
print_screen(screen)
last_print = counter
last_x = x
except StopIteration:
return score
play()