Created
December 12, 2019 07:05
-
-
Save alkemann/00c409d46e1fd4a8824cbbd1760a9ea8 to your computer and use it in GitHub Desktop.
Advent of Code, a broken day 11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from lib import get_input | |
def intcode(input_values, ram, pos=0, rel_base=0): | |
p_per_op = {1: 2, 2: 2, 3: 0, 4: 1, 5: 2, 6: 2, 7: 2, 8: 2, 9: 1, 99: 0} | |
move_per_op = {1: 4, 2: 4, 3: 2, 4: 2, 5: 0, 6: 0, 7: 4, 8: 4, 9: 2, 99: 0} | |
wr_per_po = {1: True, 2: True, 3: True, 4: False, 5: False, 6: False, 7: True, 8: True, 9: True, 99: False} | |
while True: | |
op_str = str(ram[pos]) | |
op = int(op_str[-2:]) | |
nr_of_parameters = p_per_op[op] | |
para_is_immediate = [t == "1" for t in ("0000" + op_str[:-2])] | |
para_is_immediate.reverse() | |
para_is_relative = [t == "2" for t in ("0000" + op_str[:-2])] | |
para_is_relative.reverse() | |
parameters = ram[pos + 1:pos + nr_of_parameters + 1] | |
write_is_relative = wr_per_po[op] and para_is_relative[nr_of_parameters] | |
write_to = write_val = None | |
def ll(i): | |
try: | |
if para_is_immediate[i]: | |
return parameters[i] | |
elif para_is_relative[i]: | |
return ram[rel_base + parameters[i]] | |
else: | |
return ram[parameters[i]] | |
except IndexError: | |
return 0 | |
parameters = [ll(i) for i in range(len(parameters))] | |
if op == 99: | |
return None, -1, None | |
elif op == 1: | |
left, right = parameters | |
write_to = ram[pos + 3] | |
write_val = left + right | |
elif op == 2: | |
left, right = parameters | |
write_val = left * right | |
write_to = ram[pos + 3] | |
elif op == 3: | |
write_to = ram[pos + 1] | |
write_val = input_values.pop(0) | |
elif op == 4: | |
# print("OUT", parameters[0]) | |
return parameters[0], pos + move_per_op[op], rel_base | |
elif op == 5: | |
left, right = parameters | |
pos = right if left != 0 else pos + 3 | |
elif op == 6: | |
left, right = parameters | |
pos = right if left == 0 else pos + 3 | |
elif op == 7: | |
left, right = parameters | |
write_to = ram[pos + 3] | |
write_val = 1 if left < right else 0 | |
elif op == 8: | |
left, right = parameters | |
write_to = ram[pos + 3] | |
write_val = 1 if left == right else 0 | |
elif op == 9: | |
rel_base += parameters[0] | |
if write_to is not None: | |
write_to += rel_base if write_is_relative else 0 | |
if write_to >= len(ram): | |
ram = list(padded(ram, 0, write_to + 1)) | |
ram[write_to] = write_val | |
pos += move_per_op[op] | |
# dir: 0:N 1:E 2:S 3:W | |
def part1(): | |
ram = instructions.copy() | |
pos = rb = x = y = d = 0 | |
painted = {} | |
while True: | |
inn = 0 if (x, y) not in painted or painted[(x, y)] == 0 else 1 | |
pout, pos, rb = intcode([inn], ram, pos, rb) | |
if pos == -1: break | |
painted[(x, y)] = pout | |
tout, pos, rb = intcode([], ram, pos, rb) | |
d = (d + 1) % 4 if tout == 1 else (d - 1) % 4 | |
x += 1 if d == 1 else -1 if d == 3 else 0 | |
y += 1 if d == 2 else -1 if d == 0 else 0 | |
show_paint_job(painted) | |
return len(painted.keys()) | |
def show_paint_job(painted): | |
blank = ' '*100 | |
display = [' '*100]*100 | |
for pixel in painted: | |
x, y = pixel | |
x += 50 | |
y += 50 | |
p = " " if painted[pixel] == 0 else "█" | |
display[y] = display[y][:x] + p + display[y][x+1:] | |
for line in display: | |
if line != blank: | |
print(line) | |
def part2(): | |
ram = instructions.copy() | |
pos = rb = x = y = d = 0 | |
painted = {(0,0): 1} | |
while True: | |
inn = 0 if (x, y) not in painted or painted[(x, y)] == 0 else 1 | |
pout, pos, rb = intcode([inn], ram, pos, rb) | |
if pos == -1: break | |
painted[(x, y)] = pout | |
tout, pos, rb = intcode([], ram, pos, rb) | |
d = (d + 1) % 4 if tout == 1 else (d - 1) % 4 | |
x += 1 if d == 1 else -1 if d == 3 else 0 | |
y += 1 if d == 2 else -1 if d == 0 else 0 | |
show_paint_job(painted) | |
if __name__ == '__main__': | |
print("Day 7") | |
instructions = [int(i) for i in get_input("d11")[0].split(',')] | |
print("Part 1", part1()) | |
print("Part 2", part2()) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment