class RescueDrone: def __init__(self, code): self.brain = Intcode() self.brain.load(code) self.commands = { "n": "north", "s": "south", "e": "east", "w": "west", "t": "take", "d": "drop", "i": "inv" } def act(self, command=""): if command != "": if command[0] in self.commands: command = self.commands[command[0]] + command[1:] for c in command: self.brain.add_input(ord(c)) self.brain.add_input(ord("\n")) self.brain.run() outputs = map(chr, map(int, self.brain.get_all_outputs().split())) self.print_output(outputs) def print_output(self, outputs): for c in outputs: print(c, end="")
class Arcade: def __init__(self): self.cpu = Intcode() self.screen = {} def load_game(self, code): self.cpu.load(code) def insert_coins(self, n): self.cpu.code[0] = 2 def draw_screen(self): tiles = {0: "░░", 1: "██", 2: "▓▓", 3: "==", 4: "()"} if (-1, 0) in self.screen: score = self.screen[(-1, 0)] else: score = -1 print(f"██ {score:60d} points ██") for row in range(20): for col in range(38): if (col, row) in self.screen: tile = tiles[self.screen[(col, row)]] print(tile, end="") print() def auto_move(self): for x, y in self.screen.keys(): if self.screen[(x, y)] == 3: paddle = x if self.screen[(x, y)] == 4: ball = x if paddle < ball: return "d" elif paddle > ball: return "a" else: return "s" def run(self, automatic): inputs = {"": 0, "a": -1, "s": 0, "d": 1, "j": -1, "k": 0, "l": 1} while self.cpu.state != "halted": self.cpu.run() while len(self.cpu.outputs): if len(self.cpu.outputs) >= 3: x = self.cpu.outputs.popleft() y = self.cpu.outputs.popleft() tile = self.cpu.outputs.popleft() self.screen[(x, y)] = tile else: print( f"ERROR: Encountered a faulty cpu output: {list(self.cpu.outputs)}" ) break if self.cpu.state != "halted": self.draw_screen() if not automatic: inp = input("move: ") else: inp = self.auto_move() self.cpu.add_input(inputs[inp])
def ask_about_position(data, x, y): beam = Intcode() beam.load(data) beam.add_input(x) beam.add_input(y) beam.run() return beam.get_output()
def run(): data = load_data("Day09.txt") comp = Intcode() comp.load(data) comp.add_input(1) comp.run() print(f"The BOOST keycode is {comp.get_output()}") comp.load(data) comp.add_input(2) comp.run() print(f"The coordinate is {comp.get_output()}")
def __init__(self, count, code): self.nodes = [] self.queues = [] self.iddles = [0] * count self.nat = (0, 0) self.nat_timer = 0 self.nat_history = set() for i in range(count): node = Intcode() node.load(code) node.add_input(i) self.nodes.append(node) self.queues.append(deque())
def test_compute_intcode(self): computer = Intcode([ 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99 ]) computer.execute() self.assertEqual([ 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99 ], computer.outputs) computer = Intcode([1102, 34915192, 34915192, 7, 4, 7, 99, 0]) computer.add_input(1) output = computer.execute() self.assertEqual(1219070632396864, output) computer = Intcode([104, 1125899906842624, 99]) computer.add_input(1) output = computer.execute() self.assertEqual(1125899906842624, output)
def paint_area(program, initial_color): area = {} position = (0, 0) direction = (0, 1) computer = Intcode(program) while True: color = area.get(position, initial_color) computer.add_input(color) paint = computer.run() if paint is None: break area[position] = paint turn = computer.run() direction = compute_direction_after_turn(direction, turn) position = compute_position_after_forward_move(position, direction) return area
class VacuumRobot: def __init__(self): self.brain = Intcode() def load(self, code): self.brain.load(code) def grab_camera(self): self.brain.run() return "".join(map(chr, map(int, self.brain.get_all_outputs().split()))) def run_path(self, order, subpaths): self.brain.code[0] = 2 # switch to the path following mode line = list(map(ord, ",".join(map(str, order)) + "\n")) for c in line: self.brain.add_input(c) for path in subpaths: line = list(map(ord, ",".join(map(str, path)) + "\n")) for c in line: self.brain.add_input(c) line = list(map(ord, "n\n")) for c in line: self.brain.add_input(c) self.brain.run() outputs = self.brain.get_all_outputs().split() return outputs[-1]
from intcode import Intcode def load_input(): with open("day9/input.txt") as f: instructions = f.read() return [int(x) for x in instructions.strip().split(",")] if __name__ == "__main__": program = load_input() computer = Intcode(program) computer.add_input(1) print(computer.execute()) computer = Intcode(program) computer.add_input(2) print(computer.execute())
class RepairDroid: def __init__(self): self.brain = Intcode() self.x = 0 self.y = 0 def load(self, code): self.brain.load(code) def show_map(self, corridors): x0, x1, y0, y1 = 0, 0, 0, 0 for place in corridors.keys(): if place[0] < x0: x0 = place[0] if place[0] > x1: x1 = place[0] if place[1] < y0: y0 = place[1] if place[1] > y1: y1 = place[1] for y in range(y0, y1 + 1): for x in range(x0, x1 + 1): if x == self.x and y == self.y: c = "[]" elif (x, y) in corridors: if corridors[(x, y)] == -1: c = "░░" elif corridors[(x, y)] == -2: c = "██" elif corridors[(x, y)] == -10: c = "GG" else: c = " " print(c, end="") print() def explore(self, corridors): direction = 0 dir_to_movement = {0: 1, 1: 4, 2: 2, 3: 3} dx = {0: 0, 1: 1, 2: 0, 3: -1} dy = {0: -1, 1: 0, 2: 1, 3: 0} while True: if self.x == 0 and self.y == 0 and len( corridors) > 10: # back at the beginning break self.brain.add_input(dir_to_movement[direction]) self.brain.run() info = self.brain.get_output() if info == 0: # hit a wall corridors[(self.x + dx[direction], self.y + dy[direction])] = -2 direction = (direction + 1) % 4 elif info == 1: # moved self.x += dx[direction] self.y += dy[direction] corridors[(self.x, self.y)] = -1 direction = (direction + 3) % 4 elif info == 2: # found generator self.x += dx[direction] self.y += dy[direction] corridors[(self.x, self.y)] = -10 direction = (direction + 3) % 4 self.show_map(corridors)
class Robot(object): def __init__(self, program): self.computer = Intcode(program) self.area_map = {(0, 0): (EMPTY_CELL, 0)} self.position = (0, 0) self.tank_position = None def explore(self, previous_moves=None): if previous_moves is None: previous_moves = [] has_moved = False for direction, code in directions.items(): new_position = (self.position[0] + direction[0], self.position[1] + direction[1]) if new_position in self.area_map: continue self.computer.add_input(code) output = self.computer.run() if output == 0: self.area_map[new_position] = (WALL, None) if output == 2: self.tank_position = new_position self.area_map[new_position] = (OXYGEN_TANK, len(previous_moves) + 1) has_moved = True self.position = new_position self.explore(previous_moves=previous_moves + [direction]) if output == 1: self.area_map[new_position] = (EMPTY_CELL, len(previous_moves) + 1) has_moved = True self.position = new_position self.explore(previous_moves=previous_moves + [direction]) if not has_moved and previous_moves: last_move = previous_moves.pop() direction = (-last_move[0], -last_move[1]) self.computer.add_input(directions[direction]) self.computer.run() self.position = (self.position[0] + direction[0], self.position[1] + direction[1]) self.explore(previous_moves) def compute_area_matrix(self): cells = self.area_map.keys() min_x, min_y = min(cells, key=lambda x: x[0])[0], min(cells, key=lambda x: x[1])[1] max_x, max_y = max(cells, key=lambda x: x[0])[0], max(cells, key=lambda x: x[1])[1] matrix = [[" " for _ in range(max_x - min_x + 1)] for _ in range(max_y - min_y + 1)] for (x, y), (code, distance) in self.area_map.items(): if code == WALL: matrix[y - min_y][x - min_x] = "#" elif code == EMPTY_CELL: matrix[y - min_y][x - min_x] = " " elif code == OXYGEN_TANK: matrix[y - min_y][x - min_x] = "O" if x == y == 0: matrix[y - min_y][x - min_x] = "S" return matrix def display_area(self): for row in self.compute_area_matrix(): print("".join(row)) def compute_shortest_paths(self): grid = self.compute_area_matrix() oxygen_tank_position = next((i, j) for i, row in enumerate(grid) for j, value in enumerate(row) if value == "O") graph = {} for i, row in enumerate(grid): for j, value in enumerate(row): if value != "#": for (x, y) in ((-1, 0), (1, 0), (0, -1), (0, 1)): if 0 <= i + x < len(grid) and 0 <= j + y < len( grid[0]) and grid[i + x][j + y] != "#": if (i, j) in graph: graph[(i, j)].append((i + x, j + y)) else: graph[(i, j)] = [(i + x, j + y)] distances = {node: math.inf for node in graph} previous_nodes = {node: None for node in graph} distances[oxygen_tank_position] = 0 queue = {node for node in graph} while len(queue) > 0: node = min(queue, key=lambda node: distances[node]) queue.remove(node) for neighbor in graph[node]: t = distances[node] + 1 if t < distances[neighbor]: distances[neighbor] = t previous_nodes[neighbor] = node return distances
class SpringDroid: def __init__(self, data): self.brain = Intcode() self.brain.load(data) def walk(self, code): for line in code: for char in line: self.brain.add_input(ord(char)) self.brain.add_input(ord("\n")) for c in "WALK": self.brain.add_input(ord(c)) self.brain.add_input(ord("\n")) self.brain.run() output = list(map(int, self.brain.get_all_outputs().split())) return output def run(self, code): for items in code: line = " ".join(items) for char in line: self.brain.add_input(ord(char)) self.brain.add_input(ord("\n")) for c in "RUN": self.brain.add_input(ord(c)) self.brain.add_input(ord("\n")) self.brain.run() output = list(map(int, self.brain.get_all_outputs().split())) return output def run_and_score(self, code): for items in code: line = " ".join(items) for char in line: self.brain.add_input(ord(char)) self.brain.add_input(ord("\n")) for c in "RUN": self.brain.add_input(ord(c)) self.brain.add_input(ord("\n")) self.brain.run() output = list(map(int, self.brain.get_all_outputs().split())) outcome = output[-1] if output[-1] > 255 else 0 return self.brain.instructions_executed, outcome
class Breakout(object): def __init__(self, program, mode=None): self.program = program if mode: self.program[0] = mode self.computer = Intcode(program) def display(self): array = [[" " for _ in range(max(self.computer.outputs[::3]) + 1)] + [str(j).rjust(3)] for j in range(max(self.computer.outputs[1::3]) + 1)] for (x, y, tile) in zip(self.computer.outputs[::3], self.computer.outputs[1::3], self.computer.outputs[2::3]): if (x, y) == (-1, 0): continue symbols = {0: " ", 1: "/", 2: "#", 3: "_", 4: "O"} array[y][x] = symbols[tile] for row in array: print("".join([x.rjust(3) for x in row])) print("".join([str(i).rjust(3) for i in range(len(array[0]))])) def get_paddle_position(self): paddle = self.computer.outputs[2::3][::-1].index(3) return self.computer.outputs[::3][::-1][paddle], self.computer.outputs[ 1::3][::-1][paddle] def get_ball_position(self): ball = self.computer.outputs[2::3][::-1].index(4) return self.computer.outputs[::3][::-1][ball], self.computer.outputs[ 1::3][::-1][ball] def compute_score(self): for x, y, tile in zip(self.computer.outputs[::3][::-1], self.computer.outputs[1::3][::-1], self.computer.outputs[2::3][::-1]): if (x, y) == (-1, 0): return tile return 0 def count_blocks(self): return self.computer.outputs[2::3].count(2) def play(self): breakout.computer.execute() while not self.computer.stopped: paddle_position = self.get_paddle_position() ball_position = self.get_ball_position() if paddle_position[0] > ball_position[0]: instruction = -1 elif paddle_position[0] < ball_position[0]: instruction = 1 else: instruction = 0 self.computer.add_input(instruction) self.computer.execute()
def is_affected_by_beam(i, j, program): computer = Intcode(program) computer.add_input(i) computer.add_input(j) computer.execute() return computer.outputs[0] == 1