Skip to content

Instantly share code, notes, and snippets.

@alkemann
Created December 12, 2019 07:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alkemann/00c409d46e1fd4a8824cbbd1760a9ea8 to your computer and use it in GitHub Desktop.
Save alkemann/00c409d46e1fd4a8824cbbd1760a9ea8 to your computer and use it in GitHub Desktop.
Advent of Code, a broken day 11
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