def main(): with open("day13.txt", "r") as fp: memory = dict() for i, s in enumerate(fp.read().split(",")): memory[i] = int(s) # Part 1 screen = defaultdict(lambda: 0) output = run_program(defaultdict(lambda: 0, memory), iter([])) try: while True: x, y, v = next(output), next(output), next(output) screen[(x, y)] = v except StopIteration: pass count = 0 for v in screen.values(): if v == 2: count += 1 print(count) # Part 2 screen = defaultdict(lambda: 0) start_memory = defaultdict(lambda: 0, memory) start_memory[0] = 2 def input2(): while True: ball = None paddle = None for k, v in screen.items(): if v == 3: paddle = k elif v == 4: ball = k if paddle[0] < ball[0]: yield 1 elif paddle[0] > ball[0]: yield -1 else: yield 0 output = run_program(start_memory, input2()) try: while True: x, y, v = next(output), next(output), next(output) screen[(x, y)] = v except StopIteration: pass print(screen[(-1, 0)])
def run_ascii(memory, input): output_iter = run_program(defaultdict(lambda: 0, memory), (ord(c) for c in input)) for c in output_iter: if c > 128: print(c) elif chr(c) == "\n": print() else: print(chr(c), end="")
def run_robot(memory, start_panels): panels = defaultdict(lambda: 0, start_panels) directions = [(0, -1), (-1, 0), (0, 1), (1, 0)] direction = 0 position = (0, 0) def input1(): while True: yield panels[position] execution = run_program(defaultdict(lambda: 0, memory), input1()) try: while True: color = next(execution) rotation = next(execution) panels[position] = color direction = (direction + (1 if rotation == 1 else -1)) % len(directions) position = (position[0] + directions[direction][0], position[1] + directions[direction][1]) except StopIteration: pass return panels
def main(): with open("day25.txt", "r") as fp: memory = dict() for i, s in enumerate(fp.read().split(",")): memory[i] = int(s) # Part 1 # # Stables -- Crew Quarters - Engineering - Corridor # | SCP - Arcade Sick Bay # | Kitchen ------ Hallway # Storage --- Passages -- GWC --- Science Lab -- Holodeck ---- Warp Drive Maintenance # Hot Chocolate Fountain Hull Breach # # # Holodeck: giant electromagnet (don't take this) # Warp Drive Maintenance: ornament # Kitchen: escape pod (leaves the ship) # Sick Bay: dark matter # Crew Quarters: astrolabe # Engineering: hologram # Corridor: klein bottle # Arcade: molten lava (don't take this) # GWC: candy cane # Passages: photons (don't take this) # Storage: tambourine last_output = "Command?" def brute_force_checkput(dir, items): for item in items: yield "drop " + item for i in range(2**len(items)): for bit in range(len(items)): if i & (1 << bit): yield "take " + items[bit] yield dir if "Alert!" not in last_output: break for bit in range(len(items)): if i & (1 << bit): yield "drop " + items[bit] print("NO SOLUTION FOUND!") def input1(): # First take all the items in the lower half of the ship take_all_items = "\n".join([ "north", "east", "take ornament", "north", "north", "take dark matter", "south", "south", "west", "west", "west", "take candy cane", "west", "west", "take tambourine", "east", "east", "east", "north", "take astrolabe", "east", "take hologram", "east", "take klein bottle", "west", "south", "west", ]) + "\n" for c in take_all_items: yield ord(c) items = [ "ornament", "dark matter", "candy cane", "tambourine", "astrolabe", "hologram", "klein bottle" ] # Try to pass the first Security Checkpoint (SCP) for command in brute_force_checkput("north", items): for c in command: yield ord(c) yield (ord("\n")) while True: line = input() line = line.strip() + "\n" for c in line: yield ord(c) for c in run_program(defaultdict(lambda: 0, memory), input1()): if chr(c) == "\n": print() else: print(chr(c), end="") last_output += chr(c) if last_output.endswith("Command?"): last_output = last_output[last_output.index("Command?") + 8:]
def main(): with open("day23.txt", "r") as fp: memory = dict() for i, s in enumerate(fp.read().split(",")): memory[i] = int(s) # Part 1 receive_queues = [Queue() for i in range(50)] done_queue = Queue() def receive(index): yield index while True: try: (x, y) = receive_queues[index].get_nowait() yield x yield y except Empty: yield -1 yield -1 def send(index, program): while True: dest = next(program) x = next(program) y = next(program) if dest == 255: done_queue.put_nowait(y) break receive_queues[dest].put_nowait((x, y)) senders = [ Process(target=send, args=(i, run_program(defaultdict(lambda: 0, memory), receive(i)))) for i in range(50) ] for sender in senders: sender.start() result = done_queue.get() for sender in senders: sender.terminate() print(result) # Part 2 receive_queues = [Queue() for i in range(50)] nat_value = Array(ctypes.c_long, 2) waiting = Array(ctypes.c_bool, len(receive_queues)) def receive(index): yield index while True: try: (x, y) = receive_queues[index].get_nowait() with waiting.get_lock(): waiting[index] = False yield x yield y except Empty: with waiting.get_lock(): waiting[index] = True yield -1 yield -1 def send(index, program): while True: dest = next(program) x = next(program) y = next(program) if dest == 255: with nat_value.get_lock(): nat_value[0] = x nat_value[1] = y else: receive_queues[dest].put_nowait((x, y)) senders = [ Process(target=send, args=(i, run_program(defaultdict(lambda: 0, memory), receive(i)))) for i in range(50) ] for sender in senders: sender.start() last_nat_y = None while True: sleep(0.25) with waiting.get_lock(): all_waiting = True for w in waiting: all_waiting = all_waiting and waiting if all_waiting: with nat_value.get_lock(): receive_queues[0].put_nowait((nat_value[0], nat_value[1])) if last_nat_y == nat_value[1]: break else: last_nat_y = nat_value[1] for sender in senders: sender.terminate() print(last_nat_y)
def has_beam(x, y): return next(run_program(defaultdict(lambda: 0, memory), iter([x, y]))) == 1
def main(): with open("day17.txt", "r") as fp: memory = dict() for i, s in enumerate(fp.read().split(",")): memory[i] = int(s) # Part 1 map = [[]] for c in run_program(defaultdict(lambda: 0, memory), iter([])): c = chr(c) if c == "\n": map.append([]) else: map[-1].append(c) while map[-1] == []: del map[-1] for y in range(len(map)): for x in range(len(map[y])): print(map[y][x], end="") print() result = 0 for y in range(1, len(map) - 1): for x in range(1, len(map[0]) - 1): if map[y][x] == "#" and map[y - 1][x] == "#" and map[ y + 1][x] == "#" and map[y][x + 1] == "#" and map[y][x - 1] == "#": result += x * y print(result) # Part 2 def map_get(x, y): if 0 <= y and y < len(map) and 0 <= x and x < len(map[y]): return map[y][x] else: return "." # Find the robot rx, ry = -1, -1 dx, dy = -1, -1 for y in range(len(map)): for x in range(len(map[y])): if map[y][x] == "<": dx, dy = -1, 0 rx, ry = x, y elif map[y][x] == "^": dx, dy = 0, -1 rx, ry = x, y elif map[y][x] == ">": dx, dy = 1, 0 rx, ry = x, y elif map[y][x] == "v": dx, dy = 0, 1 rx, ry = x, y # Follow the path commands = [] while True: # Go ahead commands.append(0) while map_get(rx + dx, ry + dy) == "#": commands[-1] += 1 rx, ry = rx + dx, ry + dy if commands[-1] == 0: del commands[-1] # Check for a turn if map_get(rx + dy, ry - dx) == "#": commands.append("L") dx, dy = dy, -dx elif map_get(rx - dy, ry + dx) == "#": commands.append("R") dx, dy = -dy, dx else: break commands = [str(command) for command in commands] def possible_subprograms(): for start in range(len(commands)): for slen in range(1, len(commands) - start + 1): prog = ",".join(commands[start:start + slen]) if len(prog) <= 20: yield prog possible_subprograms = set(possible_subprograms()) commands_str = ",".join(commands) found = False for a in possible_subprograms: for b in possible_subprograms: for c in possible_subprograms: prog_str = commands_str.replace(a, "A").replace(b, "B").replace( c, "C") if len(prog_str) <= 20 and PATTERN.match(prog_str): found = True break if found: break if found: break print(prog_str, a, b, c) def program_input(): prog = ( prog_str + "\n" + # main a + "\n" + # A b + "\n" + # B c + "\n" + # C "n\n" # feed ) for ch in prog: yield (ord(ch)) program_memory = defaultdict(lambda: 0, memory) program_memory[0] = 2 program_output = run_program(program_memory, program_input()) for po in program_output: if po > 128: print(po) else: pass
def main(): with open("day15.txt", "r") as fp: memory = dict() for i, s in enumerate(fp.read().split(",")): memory[i] = int(s) # Part 1 ######### map = defaultdict(lambda: " ") pos = (0, 0) map[pos] = "." input_queue = [] robot = run_program(defaultdict(lambda: 0, memory), read_input_queue(input_queue)) # 1. move up until we hit a wall input_queue.append(NORTH) output = next(robot) pos = handle_output(map, pos, input_queue[-1], output) # 2. follow the wall start_pos = pos wall_dir = NORTH while True: input_queue.append(wall_dir) output = next(robot) pos = handle_output(map, pos, input_queue[-1], output) if output != WALL: wall_dir = CCW_OF[wall_dir] else: input_queue.append(CW_OF[wall_dir]) output = next(robot) pos = handle_output(map, pos, input_queue[-1], output) if output == WALL: wall_dir = input_queue[-1] if pos == start_pos and wall_dir == NORTH: break print_map(map) # 3. DFS done = set() frontier = set([(0, 0)]) iteration = 0 oxygen_pos = None while True: for pos in frontier: if map[pos] == "x": oxygen_pos = pos break if oxygen_pos: break iteration += 1 new_frontier = set() for pos in frontier: new_frontier.update( offset(pos, off) for off in OFFSET_OF.values() if map[offset(pos, off)] != "#" and offset(pos, off) not in done) done.update(frontier) frontier = new_frontier print(iteration) # Part 2 ######### # Again just use a DFS done = set() frontier = set([oxygen_pos]) iteration = 0 while len(frontier) > 0: iteration += 1 new_frontier = set() for pos in frontier: new_frontier.update( offset(pos, off) for off in OFFSET_OF.values() if map[offset(pos, off)] != "#" and offset(pos, off) not in done) done.update(frontier) frontier = new_frontier print(iteration - 1)
def test_large_number(): program = "104,1125899906842624,99" assert run_program(program) == [1125899906842624]
def test_sixteen_digit(): program = "1102,34915192,34915192,7,4,7,99,0" assert run_program(program) == [1219070632396864]
def test_returns_self(): program = "109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99" expected_output = [int(a) for a in program.split(',')] assert run_program(program) == expected_output