from intcode import parse, emulator, REPL import re N = 'north' S = 'south' E = 'east' W = 'west' back = {N : S, S : N, W : E, E : W} def add_vec(xy, d): x, y = xy if d == N: return (x, y+1) if d == S: return (x, y-1) if d == W: return (x-1, y) if d == E: return (x+1, y) class Room: def __init__(self, mssg, path): blocks = mssg.strip().split("\n\n") head_str = blocks[0] door_str = blocks[1] item_str = '\n'.join(blocks[2:]) self.name = re.findall('=+ ([^=]+) =+', head_str)[0] self.description = re.findall(r'=\n([\s\S]+)', head_str)[-1].rstrip() self.doors = re.findall(r'- (\w+)\n?', door_str) self.items = re.findall(r'- (.+)\n?', item_str) self.path = path def __eq__(self, other): return self.name == other.name def __repr__(self): head = "== {} ==\n{}".format(self.name, self.description) doors = "Doors here lead:\n- {}".format("\n- ".join(self.doors)) items = "" if self.items == [] else "\n\nItems here:\n- {}".format("\n- ".join(self.items)) path = " -> ".join(self.path) return "{}\n\n{}{}\n{}".format(head, doors, items, path) def encode(s): return map(ord, s + '\n') def decode(lst): return ''.join(map(chr, lst)) def goto_room(repl, room): for d in room.path: repl.write(d) next(repl) def try_item(repl, item): if item in ("infinite loop", "giant electromagnet"): return False repl = repl.copy() repl.write("take " + item) next(repl) try: repl.write('') next(repl) return True except StopIteration: return False def map_ship(repl): rooms = [] items = [] def aux(path): s = next(repl) try: room = Room(s, path) except: return if room in rooms: return rooms.append(room) for item in room.items: if not try_item(repl, item): continue repl.write("take " + item) next(repl) items.append(item) for d in room.doors: repl.write(d) aux(path + [d]) repl.write(back[d]) next(repl) aux([]) return rooms, items def preproc(puzzle_input): prog = parse(puzzle_input) emul = emulator(prog) repl = REPL(emul, decode=decode, encode=encode) rooms, items = map_ship(repl) checkpoint = list(filter(lambda room : room.name == "Security Checkpoint", rooms))[0] goto_room(repl, checkpoint) return repl def partI(repl): for item in ["coin", "mutex", "astronaut ice cream", "dehydrated water"]: repl.write("drop " + item) next(repl) repl.write("north") s = next(repl) return re.findall(r'\d+', s)[0] def partII(_): return "No solution"