def parta(txt: str): screen = {} p = IntcodeProgram.parse(txt) p.run() for x, y, tile_id in chunk([*p.outputs], 3): screen[(x, y)] = tile_id return Counter(screen.values())[2]
def partb(txt: str): network: list[IntcodeProgram] = [] for network_address in range(50): p = IntcodeProgram.parse(txt) p.write_input(network_address) network.append(p) last_y_sent_by_nat = None nat = None while True: packets_sent = 0 for p in network: p.run() if p.is_waiting_for_input(): p.write_input(-1) p.run() if len(p.outputs) > 0: assert len(p.outputs) % 3 == 0 while len(p.outputs) > 0: packets_sent += 1 destination, x, y = (p.outputs.popleft() for _ in range(3)) if destination == 255: nat = (x, y) else: network[destination].write_input(x) network[destination].write_input(y) is_idle = packets_sent == 0 if is_idle: x, y = nat if y == last_y_sent_by_nat: return last_y_sent_by_nat network[0].write_input(x) network[0].write_input(y) last_y_sent_by_nat = y
def partb(txt: str): screen = {} score = None p = IntcodeProgram.parse(txt) p[0] = 2 ball_x, paddle_x = None, None while not p.terminated: p.run_next() if len(p.outputs) > 0 and len(p.outputs) % 3 == 0: x, y, tile_id = (p.outputs.popleft() for _ in range(3)) if (x, y) == (-1, 0): score = tile_id else: screen[(x, y)] = tile_id if tile_id == 4: ball_x = x elif tile_id == 3: paddle_x = x if p.is_waiting_for_input(): # print(display(screen, score)) joystick = 0 if ball_x != paddle_x: joystick = 1 if ball_x > paddle_x else -1 p.write_input(joystick) return score
def get_complete_map(txt: str): p = IntcodeProgram.parse(txt) p.run() grid = {} explore(p, grid) # print(display(grid)) # see the grid return grid
def partb(txt: str): for noun, verb in itertools.product(range(0, 100), repeat=2): p = IntcodeProgram.parse(txt) p[1] = noun p[2] = verb p.run() if p[0] == 19690720: return 100 * noun + verb
def test_rel_base(): p = IntcodeProgram.parse("109,19,204,-34") p[1985] = 1234567890 p._relative_base = 2000 p.run_next() assert p._relative_base == 2019 p.run_next() assert len(p.outputs) == 1 assert p.outputs[0] == 1234567890
def partb(txt: str): p = IntcodeProgram.parse(txt) assert p[0] == 1 p[0] = 2 # wake up the robot p.run() # get the initial video feed video_feed, _main_prompt = "".join(chr(c) for c in p.outputs).split("\n\n") # plan the route full = full_route(video_feed) plan = [",".join(x) for x in plan_route(full)] # input the plan for f in plan: for x in f: p.write_input(ord(x)) p.write_input(ord("\n")) # # for continuous output (while testing) # p.write_input(ord("y")) # p.write_input(ord("\n")) # leftover = "" # while not p.terminated: # try: # p.run(max_steps=100) # except: # pass # if len(p.outputs) > 0: # if p.outputs[-1] in range(0x110000): # leftover += "".join(chr(x) for x in p.outputs) # else: # leftover += "".join(chr(x) for x in [*p.outputs][:-1]) # # if we have one or more full screens # if "\n\n" in leftover: # chunks = leftover.split("\n\n") # # print each full screen # for c in chunks[:-1]: # print(c) # print() # # and set leftover to whatever we didn't print # leftover = chunks[-1] # if p.outputs[-1] not in range(0x110000): # return p.outputs[-1] # p.outputs.clear() # no to continuous output p.write_input(ord("n")) p.write_input(ord("\n")) # execute p.run() return p.outputs[-1]
def parta(txt: str): m = 0 for phase_setting_seq in itertools.permutations(range(5)): amplifiers = [IntcodeProgram.parse(txt) for _ in range(5)] prev = 0 for a, n in zip(amplifiers, phase_setting_seq): a.write_input(n) a.write_input(prev) a.run() prev = a.outputs[0] m = max(m, prev) return m
def partb(txt: str): m = 0 for phase_setting_seq in itertools.permutations(range(5, 10)): amplifiers = [IntcodeProgram.parse(txt) for _ in range(5)] for a, n in zip(amplifiers, phase_setting_seq): a.write_input(n) prev = 0 while not amplifiers[-1].terminated: for a in amplifiers: a.write_input(prev) a.run() prev = a.outputs[-1] m = max(m, prev) return m
def parta(txt: str): network: list[IntcodeProgram] = [] for network_address in range(50): p = IntcodeProgram.parse(txt) p.write_input(network_address) network.append(p) while True: for p in network: p.run() if p.is_waiting_for_input(): p.write_input(-1) p.run() if len(p.outputs) > 0: assert len(p.outputs) % 3 == 0 while len(p.outputs) > 0: destination, x, y = (p.outputs.popleft() for _ in range(3)) if destination == 255: return y network[destination].write_input(x) network[destination].write_input(y)
def parta(txt: str): p = IntcodeProgram.parse(txt) ship_map = {} location = handle_move(p, None, ship_map, None) explore(p, ship_map, location) # move to the security checkpoint TARGET_ROOM = "Security Checkpoint" path_to_checkpoint = pathfind(location, TARGET_ROOM, ship_map) for direction in path_to_checkpoint: location = handle_move(p, direction, ship_map, location) # direction to move once in security checkpoint direction = next(d for d, l in get_doors(ship_map, location).items() if l == TARGET_ROOM) # get past the security checkpoint all_items = get_inventory(p) for size in range(len(all_items)): for perm in itertools.combinations(all_items, r=size): # get the right items perm = set(perm) inv = get_inventory(p) to_drop = inv - perm to_take = perm - inv for item in to_drop: drop(p, item) for item in to_take: take(p, item) # try to enter result = send_cmd(p, direction) # if we're in a new location, it worked! if not result.startswith(f"== {TARGET_ROOM} =="): return next(int(x) for x in result.split() if x.isnumeric())
def parta(txt: str): p = IntcodeProgram.parse(txt) p[1] = 12 p[2] = 2 p.run() return p[0]
def test_negative_int(): p = IntcodeProgram.parse("1101,100,-1,4,0") p.run() assert p[4] == 99
def helper(program, input, expected): p = IntcodeProgram.parse(program) p.write_input(input) p.run() assert len(p.outputs) == 1 and p.outputs[0] == expected
def test_output_sixteen_digit_number(): p = IntcodeProgram.parse("1102,34915192,34915192,7,4,7,99,0") p.run() assert len(p.outputs) == 1 assert len(str(p.outputs[0])) == 16
def test_parameter_modes(): p = IntcodeProgram.parse("1002,4,3,4,33") p.run() assert ",".join(map(str, p.memory)) == "1002,4,3,4,99"
def parta(txt: str): p = IntcodeProgram.parse(txt) p.write_input(1) p.run() assert all(n == 0 for n in [*p.outputs][:-1]) return p.outputs[-1]
def test_output_large_number(): p = IntcodeProgram.parse("104,1125899906842624,99") p.run() assert len(p.outputs) == 1 assert p.outputs[0] == 1125899906842624
def parta(txt: str): p = IntcodeProgram.parse(txt) p.run() video_feed = "".join(chr(c) for c in p.outputs) return sum_of_alignment_parameters(video_feed)
def test_quine(): quine = "109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99" p = IntcodeProgram.parse(quine) p.run() assert ",".join(map(str, p.outputs)) == quine
def partb(txt: str): p = IntcodeProgram.parse(txt) p.write_input(5) p.run() assert len(p.outputs) == 1 return p.outputs[0]