from lib import get_data, str_to_ints, add2 from d9 import Amp DIRS = {1: (-1, 0), 2: (1, 0), 3: (0, -1), 4: (0, 1)} PATH_REVERSED = {1: 2, 2: 1, 3: 4, 4: 3} def print_field(fields, walls, pos): dim = 40 for y in range(-dim, dim + 1): row = "" for x in range(-dim, dim + 1): if (y, x) == pos: row += "X" elif (y, x) in fields: row += "." elif (y, x) in walls: row += "|" else: row += " " print(row) def part_1(data): xs = str_to_ints(data) a = Amp(xs) walls = set() pos = (0, 0) target = None dir = None path = [] dir_cmds_for_pos = {pos: [1, 2, 3, 4]} while not a.done: if len(dir_cmds_for_pos[pos]) > 0: dir_cmd = dir_cmds_for_pos[pos].pop() dir = DIRS[dir_cmd] new_pos = add2(pos, dir) if new_pos in dir_cmds_for_pos: continue a.feed(dir_cmd) a.go() status = a.pop() if status == 0: walls.add(new_pos) elif status == 1: pos = new_pos path.append(dir_cmd) elif status == 2: pos = new_pos path.append(dir_cmd) target = pos if pos not in dir_cmds_for_pos: dir_cmds_for_pos[pos] = [1, 2, 3, 4] elif len(path) > 0: dir_cmd = PATH_REVERSED[path.pop()] dir = DIRS[dir_cmd] pos = add2(pos, dir) a.feed(dir_cmd) a.go() status = a.pop() assert status == 1 or status == 2 elif target is not None: break else: break fields = set(dir_cmds_for_pos.keys()) # print_field(fields, walls, pos) seen = set() to_visit = [(0, 0)] steps = 0 while len(to_visit) > 0: new = [] for current in to_visit: if current == target: print(steps) seen.add(current) for dir in DIRS.values(): nb = add2(current, dir) if nb in fields and nb not in seen: new.append(nb) to_visit = new steps += 1 seen = set() to_visit = [target] steps = 0 while len(to_visit) > 0: new = [] for current in to_visit: seen.add(current) for dir in DIRS.values(): nb = add2(current, dir) if nb in fields and nb not in seen: new.append(nb) to_visit = new steps += 1 print(steps - 1) def main(): data = get_data(__file__) part_1(data) if __name__ == "__main__": main()