class PaintingRobot: def __init__(self, input_file=None, echo=True): if input_file: self.computer = IntcodeComputer(input_file, echo=echo) else: self.computer = IntcodeComputer(echo=echo) # 0 UP, 1 RIGHT, 2 DOWN, 3 LEFT self.direction = 0 self.position = (0, 0) self.painted_tiles = {} self.echo = echo def run(self): self.paint_tile(self.position, 1) running = True while running: color = self.get_tile_color(self.position) self.computer.set_input([color]) self.computer.execute_program() output = self.computer.get_output_values() self.paint_tile(self.position, output[0]) if output[1] == 0: self.rotate_left() elif output[1] == 1: self.rotate_right() else: print('Error: Invalid rotation direction') break self.move_forward() if self.computer.finished: running = False print('Robot is finished') num_tiles = len(self.painted_tiles) print('Num tiles painted %d' % num_tiles) def rotate_left(self): self.direction -= 1 if self.direction < 0: self.direction = 3 if self.echo: print('Rotating Left. New direction %d' % self.direction) def rotate_right(self): self.direction += 1 if self.direction > 3: self.direction = 0 if self.echo: print('Rotating Right. New direction %d' % self.direction) def move_forward(self): move_x, move_y = 0, 0 if self.direction == 0: move_y = -1 elif self.direction == 1: move_x = 1 elif self.direction == 2: move_y = 1 elif self.direction == 3: move_x = -1 pos_x, pos_y = self.position self.position = pos_x + move_x, pos_y + move_y if self.echo: print('Moving to position (%d, %d)' % (self.position[0], self.position[1])) def get_tile_color(self, tile_pos): if tile_pos not in self.painted_tiles: return 0 else: return self.painted_tiles[tile_pos] def paint_tile(self, tile_pos, color): self.painted_tiles[tile_pos] = color if self.echo: print('Painting tile (%d, %d) color %d' % (tile_pos[0], tile_pos[1], color)) def output_tiles(self): min_x, max_x = None, None min_y, max_y = None, None for key in self.painted_tiles: if min_x is None or key[0] < min_x: min_x = key[0] if max_x is None or key[0] > max_x: max_x = key[0] if min_y is None or key[1] < min_y: min_y = key[1] if max_y is None or key[1] > max_y: max_y = key[1] for y in range(min_y, max_y + 1): for x in range(min_x, max_x + 1): pos = x, y if pos in self.painted_tiles and self.painted_tiles[pos] == 1: print('#', end='') else: print(' ', end='') print('\n', end='')
class ScaffoldInterface: def __init__(self, file_str=None): self.computer = IntcodeComputer(file_str, echo=False) def run(self): self.computer.run() output = self.computer.get_output_values() self.scaffolding = [[]] for tile in output: if tile == 10: self.scaffolding.append([]) # print('\n', end='') else: self.scaffolding[-1].append(tile) # print(chr(tile), end='') self.scaffolding = self.scaffolding[0:-2] self.print_scaffolding() self.count_intersections() def print_scaffolding(self): height = len(self.scaffolding) width = len(self.scaffolding[0]) # print('%d, %d' % (width, height)) for y in range(height): for x in range(width): tile = self.scaffolding[y][x] print(chr(tile), end='') print('\n', end='') def count_intersections(self): height = len(self.scaffolding) width = len(self.scaffolding[0]) intersections = [] for y in range(height): for x in range(width): tile = self.scaffolding[y][x] if chr(tile) is not '#': print('%s is not #' % tile) continue if y > 0 and chr(self.scaffolding[y-1][x]) is not '#': continue if y < height-1 and chr(self.scaffolding[y+1][x]) is not '#': continue if x > 0 and chr(self.scaffolding[y][x-1]) is not '#': continue if x < width-1 and chr(self.scaffolding[y][x+1]) is not '#': continue intersections.append((x, y)) intersection_alignment_sum = 0 for intersection in intersections: intersection_alignment_sum += intersection[0] * intersection[1] print(intersection_alignment_sum)
class ArcadeCabinet: def __init__(self, file=None, echo=True): if file is None: self.computer = IntcodeComputer(echo=echo) else: self.computer = IntcodeComputer(file, echo=echo) self.width, self.height = 0, 0 self.grid = [] def run(self): self.computer.execute_program() output = self.computer.get_output_values() for i in range(0, len(output), 3): x = output[i] y = output[i+1] tile = output[i+2] self.set_tile(x, y, tile) self.print_grid() print('Number Blocks: %d' % self.count_blocks()) def set_tile(self, x, y, tile): if not self.in_bounds(x, y): self.expand_grid(x+1, y+1) self.grid[x][y] = tile def in_bounds(self, x, y): if x >= self.width or y >= self.height: return False else: return True def expand_grid(self, new_width, new_height): if new_width > self.width: add_width = new_width - self.width for i in range(add_width): self.grid.append([0 for tile in range(self.height)]) self.width = new_width if new_height > self.height: add_height = new_height - self.height for column in self.grid: column.extend([0 for tile in range(add_height)]) self.height = new_height def print_grid(self): for y in range(self.height): for x in range(self.width): tile = self.grid[x][y] print(tile, end='') print('\n', end='') def count_blocks(self): block_count = 0 for y in range(self.height): for x in range(self.width): tile = self.grid[x][y] if tile == 2: block_count += 1 return block_count
class ArcadeCabinet: def __init__(self, file=None, echo=True): if file is None: self.computer = IntcodeComputer(echo=echo) else: self.computer = IntcodeComputer(file, echo=echo) self.width, self.height = 0, 0 self.grid = [] self.score = 0 self.paddle_x = -1 def run(self): running = True while running: self.computer.execute_program() self.read_output() self.print_grid() ball_pos = self.find_ball() paddle_pos = self.find_paddle() if ball_pos[0] < paddle_pos[0]: move = -1 elif ball_pos[0] == paddle_pos[0]: move = 0 elif ball_pos[0] > paddle_pos[0]: move = 1 self.move_paddle(move) running = not self.computer.finished def read_output(self): output = self.computer.get_output_values() for i in range(0, len(output), 3): x = output[i] y = output[i+1] tile = output[i+2] if x is -1 and y is 0: self.set_score(tile) else: self.set_tile(x, y, tile) def set_tile(self, x, y, tile): if not self.in_bounds(x, y): self.expand_grid(x+1, y+1) self.grid[x][y] = tile def set_score(self, score): self.score = score def in_bounds(self, x, y): if x >= self.width or y >= self.height: return False else: return True def expand_grid(self, new_width, new_height): if new_width > self.width: add_width = new_width - self.width for i in range(add_width): self.grid.append([0 for tile in range(self.height)]) self.width = new_width if new_height > self.height: add_height = new_height - self.height for column in self.grid: column.extend([0 for tile in range(add_height)]) self.height = new_height def print_grid(self): for y in range(self.height): for x in range(self.width): tile = self.grid[x][y] # print(tile, end='') if tile == 0: print(' ', end='') elif tile == 1: print('|', end='') elif tile == 2: print('#', end='') elif tile == 3: print('-', end='') elif tile == 4: print('*', end='') print('\n', end='') print('Score: %d' % self.score) def find_ball(self): for y in range(self.height): for x in range(self.width): tile = self.grid[x][y] if tile == 4: return (x, y) def find_paddle(self): for y in range(self.height): for x in range(self.width): tile = self.grid[x][y] if tile == 3: return (x, y) def move_paddle(self, move): self.computer.set_input([move]) def count_blocks(self): block_count = 0 for y in range(self.height): for x in range(self.width): tile = self.grid[x][y] if tile == 2: block_count += 1 return block_count
from intcode_computer import IntcodeComputer if __name__ == '__main__': num_points = 0 for y in range(50): for x in range(50): computer = IntcodeComputer('./input.txt', echo=False) computer.set_input([x, y]) computer.run() output = computer.get_output_values() print(output[0], end='') if output[0] == 1: num_points += 1 print('\n', end='') print(num_points)
class ScaffoldInterface: def __init__(self, file_str=None): self.computer = IntcodeComputer(file_str, echo=False) self.scaffolding = None def run(self): self.computer.program[0] = 2 self.computer.run() output = self.computer.get_output_values() self.print_output(output) # self.save_output(output, './map.txt') self.save_scaffolding(output) self.find_path() # Main Routine routine_main = [ord(char) for char in 'A,A,B,C,B,C,B,C,B,A\n'] print('Main Len %d' % len(routine_main)) # Function A routine_A = [ord(char) for char in 'L,10,L,8,R,8,L,8,R,6\n'] print('A Len %d' % len(routine_A)) # Function B routine_B = [ord(char) for char in 'R,6,R,8,R,8\n'] print('B Len %d' % len(routine_B)) # Function C routine_C = [ord(char) for char in 'R,6,R,6,L,8,L,10\n'] print('C Len %d' % len(routine_C)) # Main: self.computer.set_input(routine_main) print(routine_main) self.computer.run() output = self.computer.get_output_values() self.print_output(output) # Function A: self.computer.set_input(routine_A) print(routine_A) self.computer.run() output = self.computer.get_output_values() self.print_output(output) # Function B: self.computer.set_input(routine_B) print(routine_B) self.computer.run() output = self.computer.get_output_values() self.print_output(output) # Function C: self.computer.set_input(routine_C) print(routine_C) self.computer.run() output = self.computer.get_output_values() self.print_output(output) # Continuous Video Feed? in_yes = [ord(char) for char in 'Y,E,S\n'] in_no = [ord(char) for char in 'N,O\n'] self.computer.set_input(in_no) self.computer.run() last_value = self.computer.get_last_value() output = self.computer.get_output_values() self.print_output(output[:-1]) print(last_value) def save_scaffolding(self, output): self.scaffolding = [[]] for val in output[:-2]: if val == ord('\n'): self.scaffolding.append([]) else: self.scaffolding[-1].append(chr(val)) self.scaffolding = self.scaffolding[:-2] def find_path(self): height = len(self.scaffolding) width = len(self.scaffolding[0]) for y in range(height): for x in range(width): tile = self.scaffolding[y][x] if tile == '^': cur_x, cur_y = x, y # print('%d, %d' % (cur_x, cur_y)) # Directions ^ v < > cur_dir = '^' path = [] print('Finding path from (%d, %d)' % (cur_x, cur_y)) while True: # Find direction to trun if cur_dir == '^' or cur_dir == 'v': if cur_x > 0 and self.scaffolding[cur_y][cur_x-1] == '#': if cur_dir == '^': # print('L') path.append('L') cur_dir = '<' else: # print('R') path.append('R') cur_dir = '<' elif cur_x < width-1 and self.scaffolding[cur_y][cur_x+1] == '#': if cur_dir == '^': # print('R') path.append('R') cur_dir = '>' else: # print('L') path.append('L') cur_dir = '>' else: print('Reached the end at (%d, %d) facing %s' % (cur_x, cur_y, cur_dir)) break elif cur_dir == '<' or cur_dir == '>': if cur_y > 0 and self.scaffolding[cur_y-1][cur_x] == '#': if cur_dir == '<': # print('R') path.append('R') cur_dir = '^' else: # print('L') path.append('L') cur_dir = '^' elif cur_y < height-1 and self.scaffolding[cur_y+1][cur_x] == '#': if cur_dir == '<': # print('L') path.append('L') cur_dir = 'v' else: # print('R') path.append('R') cur_dir = 'v' else: print('Reached the end at (%d, %d) facing %s' % (cur_x, cur_y, cur_dir)) break else: print('Error: Invalid direction %s' % cur_dir) # Count steps until off scaffolding step_x, step_y = 0, 0 if cur_dir == '^': step_y = -1 elif cur_dir == 'v': step_y = 1 elif cur_dir == '<': step_x = -1 elif cur_dir == '>': step_x = 1 else: print('Error: Invalid direction %s' % cur_dir) distance = 0 next_tile = self.scaffolding[cur_y+step_y][cur_x+step_x] while next_tile != '.': distance += 1 cur_x += step_x cur_y += step_y if cur_x + step_x < 0 or cur_x + step_x >= width or cur_y + step_y < 0 or cur_y + step_y >= height: next_tile = None break next_tile = self.scaffolding[cur_y+step_y][cur_x+step_x] # print(distance) path.append(distance) print(path) with open('./path.txt', 'w') as file: for step in path: file.write(str(step)) file.write(',') def print_output(self, output): for val in output: print(chr(val), end='') def save_output(self, output, file_str): with open(file_str, 'w') as file: for val in output: file.write(chr(val))