def part1(filename): memory = load_memory(filename, script=__file__) prog = Program(memory) run = prog.run_computer() rows = ''.join(map(chr, run)).split('\n') grid = {(x, y): cell for y, row in enumerate(rows) for x, cell in enumerate(row)} intersections = [(x, y) for x, y in grid if grid[x, y] == grid.get( (x+1, y)) == grid.get((x-1, y)) == grid.get((x, y+1)) == grid.get((x, y-1)) == '#'] return sum(x*y for x, y in intersections)
def part2(filename): memory = load_memory(filename, script=__file__) memory[0] = 2 input = parse_vararg_input( main='A,A,B,C,B,C,B,C,C,A', A='L,10,R,8,R,8', B='L,10,L,12,R,8,R,10', C='R,10,L,12,R,10', video='n' ) prog = Program(memory, input) run = prog.run_computer() return list(run)[-1]
def solve(filename): memory = load_memory(filename, script=__file__) prog = Program(memory) run = prog.run_computer() grid = defaultdict(int, {(0, 0): 1}) o2_distance = None o2_q = [] def dfs(x, y, distance): nonlocal o2_distance, o2_q for (dir_code, return_code), (dx, dy) in DIRS.items(): x1, y1 = x + dx, y + dy if (x1, y1) not in grid: prog.input.append(dir_code) status = next(run) grid[x1, y1] = status if status != 0: dfs(x1, y1, distance + 1) prog.input.append(return_code) next(run) if grid[x, y] == 2: o2_distance = distance o2_q.append((x, y)) dfs(0, 0, 0) o2_minutes = -1 while o2_q: next_q = [] for x, y in o2_q: for dx, dy in DIRS.values(): x1, y1 = x + dx, y + dy if grid[x1, y1] == 1: grid[x1, y1] = 2 next_q.append((x1, y1)) o2_minutes += 1 o2_q = next_q return (o2_distance, o2_minutes)
def part2(filename): memory = load_memory(filename, script=__file__) memory[0] = 2 prog = Program(memory) grid = {} ball_x = paddle_x = score = None block_count = 0 class PaddleInput: popleft = lambda self: sign(ball_x - paddle_x) prog.input = PaddleInput() for x, y, id in grouper(prog.run_computer(), 3): if (x, y) == (-1, 0): score = id if block_count == 0: return score else: if id == 2: block_count += 1 elif id == 3: paddle_x = x elif id == 4: ball_x = x elif id == 0 and grid.get((x, y)) == 2: block_count -= 1 grid[x, y] = id draw(grid, out=' |#-o')
class Computer(): def __init__(self, memory, id): self.id = id self.prog = Program(memory, [id], default=-1) self.run = self.prog.run_computer() def start(self, notify): try: while True: addr = next(self.run) x = next(self.run) y = next(self.run) notify(self.id, addr, x, y) except: pass
def part1(filename): memory = load_memory(filename, script=__file__) grid = {(x, y): id for x, y, id in grouper(Program(memory, []).run_computer(), 3)} draw(grid, out=' █#-o') return sum(id == 2 for (x, y), id in grid.items())
def solve(filename, initial_color): memory = load_memory(filename, script=__file__) prog = Program(memory, [initial_color]) return paint(prog, initial_color)
def scan(self, x, y): return next(Program(self.memory, [x, y]).run_computer())
def __init__(self, memory): self.prog = Program(memory, []) self.run = self.prog.run_computer()
class Game: def __init__(self, memory): self.prog = Program(memory, []) self.run = self.prog.run_computer() def get_output(self): return ''.join(until_str(map(chr, self.run), 'Command?')) def give_input(self, s): self.prog.input.extend(map(ord, s + '\n')) return self.get_output() def manipulate(self, action, item): return self.give_input(action + ' ' + item) def go(self, direction): return self.give_input(direction) def parse_output(self, output): title, doors, items, messages, mode = '', set(), [], [], '' for line in filter(None, output.split('\n')): if line.startswith('== ') and line.endswith(' =='): title, doors, items, mode = line[3:-3], set(), [], '' elif line == 'Doors here lead:': mode = 'doors' elif line == 'Items here:': mode = 'items' elif line.startswith('- '): if mode == 'doors': doors.add(line[2:]) elif mode == 'items': items.append(line[2:]) elif line != 'Command?': if mode != '': messages.append(line) return title, doors, items, messages def solve(self): rooms, usable_items = {}, [] def dfs(path, output): title, doors, items, _ = self.parse_output(output) for item in items: if item not in FORBIDDEN_ITEMS: self.manipulate('take', item) usable_items.append(item) if title not in rooms: rooms[title] = {'ch': '.', 'doors': {}, 'path': path} for d in doors: title_dest = dfs(path + [d], self.go(d)) rooms[title]['doors'][d] = title_dest if title_dest != title: self.go(OPPOSITE_DIRS[d]) return title dfs([], self.get_output()) for d in rooms[SECURITY]['path']: self.go(d) end_direction = next(d for d, name in rooms[SECURITY]['doors'].items() if name == SECURITY) carrying = set(usable_items) for b in range(2**len(usable_items)): for i, item in enumerate(usable_items): if (1 << i) & b: if item not in carrying: self.manipulate('take', item) carrying.add(item) else: if item in carrying: self.manipulate('drop', item) carrying.remove(item) title, _, _, messages = self.parse_output(self.go(end_direction)) if title != SECURITY: return int(messages[2].split(' ')[11])
def init_programs(combo, memory): return [(prog, prog.run_computer()) for prog in (Program(memory, [val]) for val in combo)]
def __init__(self, memory, id): self.id = id self.prog = Program(memory, [id], default=-1) self.run = self.prog.run_computer()
def part1(filename): memory = load_memory(filename, script=__file__) return list(Program(memory, [1]).run_computer())
def execute_springdroid(memory, input): prog = Program(memory, input) run = prog.run_computer() output = list(run) if output[-1] >= 256: return output[-1] print(''.join(map(chr, output)))