def parsed(data): comp = IntComputer(data) comp.run() txt = "".join([chr(x) for x in reversed(comp.output)]) grid = ZGrid(txt) grid.draw() return grid
def compute(data, input_val): comp = IntComputer(data, inputs=[input_val]) comp.run() result, *zeros = comp.output for zero in zeros: assert zero == 0 return result
def __init__(self): self.comp = IntComputer(data) self.world = nx.Graph() self.comp.input = self self.command_queue = deque() self.shortcuts = { "n": "north", "s": "south", "e": "east", "w": "west", "\x1b[A": "north", "\x1b[B": "south", "\x1b[C": "east", "\x1b[D": "west", } self.inverse = { "north": "south", "south": "north", "east": "west", "west": "east", } self.rooms = {} self.current_room = None self.prev_direction = None self.prev_room = None self.inventory = set() self.mode = "explore" # or "unlock" self.combo = None
def __init__(self, data): self.grid = ZGrid({0j: "."}) self.comp = IntComputer(data) self.comp.output = deque(maxlen=1) self.freezer = {0j: self.comp.freeze()} state0 = 0j AStar.__init__(self, state0, None)
class Game: def __init__(self, data): self.cpu = IntComputer(data) self.cpu.input = self self.cpu.output = deque(maxlen=3) self.paddle_position = 0 self.ball_position = 0 self.n_blocks = 0 self.score = 0 def pop(self): p = self.paddle_position b = self.ball_position return -1 if b < p else 0 if b == p else 1 def step(self): self.cpu.run(until=IntComputer.op_output) self.cpu.run(until=IntComputer.op_output) self.cpu.run(until=IntComputer.op_output) val, y, x = self.cpu.output if val == 2: self.n_blocks += 1 elif val == 3: self.paddle_position = x elif val == 4: self.ball_position = x if x == -1 and y == 0: self.score = val def play(self): while True: try: self.step() except IntComputer.Halt: return
def __init__(self, data): self.cpu = IntComputer(data) self.cpu.input = self self.cpu.output = deque(maxlen=3) self.paddle_position = 0 self.ball_position = 0 self.n_blocks = 0 self.score = 0
class Q15AStar(AStar): def __init__(self, data): self.grid = ZGrid({0j: "."}) self.comp = IntComputer(data) self.comp.output = deque(maxlen=1) self.freezer = {0j: self.comp.freeze()} state0 = 0j AStar.__init__(self, state0, None) def adjacent(self, z): self.comp.unfreeze(self.freezer[z]) for dz, input_val in neighbours.items(): self.comp.input.append(input_val) self.comp.run(until=IntComputer.op_output) [rc] = self.comp.output if rc == NACK: self.grid[z + dz] = "#" else: self.grid[z + dz] = "." self.freezer[z + dz] = self.comp.freeze() back = neighbours[-dz] self.comp.input.append(back) self.comp.run(until=IntComputer.op_output) assert self.comp.output[0] if rc == GOAL: self.target = z + dz yield z + dz def draw(self): overlay = {0: "O"} if self.target is not None: overlay[self.target] = "T" self.grid.draw(overlay=overlay)
class Robot: def __init__(self, data, colour0=0): self.brain = IntComputer(data, inputs=[colour0]) self.brain.output = deque(maxlen=2) self.position = 0 self.direction = -1j self.painted = {} def paint(self): while True: self.brain.run(until=IntComputer.op_output) self.brain.run(until=IntComputer.op_output) turn, colour = self.brain.output self.painted[self.position] = colour self.direction *= [-1j, 1j][turn] self.position += self.direction self.brain.input.append(self.painted.get(self.position, 0)) def paint_until_halt(self): try: self.paint() except IntComputer.Halt: return
def part_a(data, r1=None, r2=None): comp = IntComputer(data) if r1 is not None: comp.reg[1] = r1 if r2 is not None: comp.reg[2] = r2 comp.run() result = comp.reg[0] return result
def __init__(self, data, phase_settings): self.comps = [ IntComputer(data, inputs=[val]) for val in phase_settings ] for left, right in zip(self.comps, self.comps[1:] + [self.comps[0]]): left.output = right.input
for C in C_choices: compressed_pathABC = compressed_pathAB pathABC = pathAB while pathABC.startswith((A, B, C)): if pathABC.startswith(A): pathABC = pathABC[len(A):].lstrip(",") compressed_pathABC += "A," if pathABC.startswith(B): pathABC = pathABC[len(B):].lstrip(",") compressed_pathABC += "B," if pathABC.startswith(C): pathABC = pathABC[len(C):].lstrip(",") compressed_pathABC += "C," if not pathABC: result = compressed_pathABC.rstrip(",") if len(result) <= mem: results.append("\n".join([result, A, B, C])) return results if __name__ == "__main__": grid = parsed(data) print("part a", calibration(grid)) comp = IntComputer(data) comp.reg[0] = 2 path = get_path(grid) comp.input_text(path) comp.run() print("part b", comp.output[0])
def beam(z): comp = IntComputer(data, inputs=[int(z.imag), int(z.real)]) comp.run(until=IntComputer.op_output) [result] = comp.output return result
def test_intcode_samples(data, output): comp = IntComputer(data) comp.run() assert ",".join([str(v) for v in comp.reg.values()]) == output
WALK """ # Jump if (there's a hole 1 space away (not A) # or there's a hole 2 spaces away (not B) # or there's a hole 3 spaces away (not C)) # and there's ground 4 spaces away (NOT NOT D) # and (there's ground 8 spaces away (H) # or 5 spaces away (E)) prog_b = """\ NOT A J NOT B T OR T J NOT C T OR T J NOT D T NOT T T AND T J AND H T OR E T AND T J RUN """ for part, prog in zip("ab", [prog_a, prog_b]): comp = IntComputer(data, inputs=[ord(x) for x in reversed(prog)]) comp.run() val = comp.output.popleft() print(*[chr(x) for x in reversed(comp.output)], sep="") print("part", part, val)
class Game: def __init__(self): self.comp = IntComputer(data) self.world = nx.Graph() self.comp.input = self self.command_queue = deque() self.shortcuts = { "n": "north", "s": "south", "e": "east", "w": "west", "\x1b[A": "north", "\x1b[B": "south", "\x1b[C": "east", "\x1b[D": "west", } self.inverse = { "north": "south", "south": "north", "east": "west", "west": "east", } self.rooms = {} self.current_room = None self.prev_direction = None self.prev_room = None self.inventory = set() self.mode = "explore" # or "unlock" self.combo = None def find_path(self, to=None): last_step = None if to is None: # just go to any unexplored room... for room in self.rooms.values(): if room.name == "Security Checkpoint": continue if any(v is None for v in room.doors.values()): to = room last_step = next(k for k, v in room.doors.items() if v is None) break else: return intermediate_rooms = nx.shortest_path(self.world, self.current_room, to) path = [] for left, right in zip(intermediate_rooms, intermediate_rooms[1:]): direction = next(d for d, r in left.doors.items() if r is right) path.append(direction) if last_step is not None: path.append(last_step) if not path: # can happen if you try to find path to room but you're already there return first_step = path[0] return first_step @cached_property def combos(self): data = {} inventory = sorted(self.inventory) for i in range(len(inventory)): for combo in combinations(inventory, i): data[combo] = "new" return data @cached_property def unlock_direction(self): return next(k for k, v in self.current_room.doors.items() if v is None) def pop(self): if not self.command_queue: # command queue is exhausted, need to update status and find task to do command = "" output = self.comp.output_as_text # entered a room if output.strip().startswith("=="): parsed_room = parse_room(output) here = parsed_room["name"] if here == "Pressure-Sensitive Floor": if "ejected" in output: if "Droids on this ship are heavier" in output: self.combos[self.combo] = "too light" self.combo = None elif "Droids on this ship are lighter" in output: self.combos[self.combo] = "too heavy" self.combo = None else: log.warning("shouldn't be here: %r", output) log.debug("parsed room data: %s", parsed_room) if here not in self.rooms: log.debug("entered new room %r, adding to graph", parsed_room) new_room = self.rooms[here] = Room(**parsed_room) if self.prev_room is not None: back = self.inverse[self.prev_direction] self.world.add_edge( new_room, self.prev_room, **{ self.prev_direction: new_room, back: self.prev_room }, ) new_room.doors[back] = self.prev_room self.prev_room.doors[self.prev_direction] = new_room else: self.world.add_node(new_room) self.current_room = self.rooms[here] if here == "Pressure-Sensitive Floor": if "ejected" in output: # actually we got kicked out self.current_room = self.rooms["Security Checkpoint"] # update inventory of self and rooms for line in output.splitlines(): if line.startswith("You take the "): item = line[13:-1] self.current_room.items.remove(item) self.inventory.add(item) if line.startswith("You drop the "): item = line[13:-1] self.inventory.remove(item) self.current_room.items.append(item) # echo on self.comp.output.clear() print(output, end="", flush=True) # pick up any crap we find lying around if self.mode == "explore": for item in self.current_room.items: if item not in blacklist: log.info("autotaking %r", item) command += f"take {item}\n" # there was nothing to take, explore around the ship if self.mode == "explore" and not command: step = self.find_path() if step is not None: command = step else: # we've explored everything, proceed to checkpoint self.mode = "unlock" command = self.find_path( to=self.rooms["Security Checkpoint"]) if command is None: command = "inv" else: self.prev_direction = command self.prev_room = self.current_room log.info("entering command %r", command) # continue proceeding to checkpoint if self.mode == "unlock": if self.current_room.name != "Security Checkpoint": command = self.find_path( to=self.rooms["Security Checkpoint"]) self.prev_direction = command self.prev_room = self.current_room if self.mode == "unlock" and not command: assert self.current_room.name == "Security Checkpoint" if self.combo is None: self.combo = next(k for k, v in self.combos.items() if v == "new") combo = set(self.combo) diff = combo ^ self.inventory for item in diff: if item in self.inventory: command = f"drop {item}" else: assert item in combo and item not in self.inventory command = f"take {item}" break else: assert combo == self.inventory log.info("trying combo %s", combo) command = self.unlock_direction # don't know what to do if not command: # interactive fallback command = input() if not command: # so that pressing "enter" at the prompt adds some useful context if self.world: # soft dependency on https://github.com/cosminbasca/asciinet try: from asciinet import graph_to_ascii print(graph_to_ascii(self.world)) except Exception as err: log.warning("Couldn't graph the space: %r", err) print("current room:", self.current_room.name) print(self.current_room.description) print("doors:", "/".join(self.current_room.doors)) print("inventory:", ", ".join(sorted(self.inventory))) # a convenience shortcut to take the item here if command == "t" and len(self.current_room.items) == 1: [item] = self.current_room.items command = f"take {item}" # allows to use the arrow keys or enter just "n" instead of typing "north" command = self.shortcuts.get(command, command) if not command.endswith("\n"): command += "\n" for char in command: self.command_queue.appendleft(ord(char)) return self.command_queue.pop() def play(self): self.comp.run() txt = self.comp.output_as_text if "Analysis complete! You may proceed." not in txt: log.warning("should be done but: %r", txt) raise Exception [code] = [word for word in txt.split() if word.isdigit()] print("part a", code)
def __init__(self, data, colour0=0): self.brain = IntComputer(data, inputs=[colour0]) self.brain.output = deque(maxlen=2) self.position = 0 self.direction = -1j self.painted = {}
def compute(data, inputs=()): comp = IntComputer(data, inputs=inputs) comp.run() result = ",".join([str(x) for x in reversed(comp.output)]) return result
def __init__(self, data): self.y0 = set() self.xy = None, None self.comps = [IntComputer(data, inputs=[i]) for i in range(50)] self.done = False