コード例 #1
0
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='')
コード例 #2
0
def part_two():
    code = get_code()
    computer = IntcodeComputer()
    computer.set_input(5)
    computer.execute_program(code)
コード例 #3
0
class DroidController:
    def __init__(self, file_str, echo=True):
        self.computer = IntcodeComputer(file_str, echo=False)
        self.x, self.y = 0, 0
        self.min_x, self.max_x = 0, 0
        self.min_y, self.max_y = 0, 0

        self.map = {(self.x, self.y): '.'}
        self.path = []
        self.target = None

    def print_map(self):
        for y in range(self.min_y, self.max_y + 1):
            for x in range(self.min_x, self.max_x + 1):
                if (x, y) in self.map:
                    if (self.x, self.y) == (x, y):
                        print('D', end='')
                    else:
                        tile = self.map[(x, y)]
                        print(tile, end='')
                else:
                    print(' ', end='')

            # New Line
            print('\n', end='')

    def find_all_unexplored(self):
        # Find all unexplored tiles
        all_unexplored = []
        for coord in self.map:
            tile = self.map[coord]
            if tile == '.' or tile == 'O':
                unexplored = self.check_unexplored(coord)
                all_unexplored.extend(unexplored)

        return all_unexplored

    def find_nearest_unexplored(self):
        '''
		Returns the (x, y) coordinate of the nearest manhatten distance unexplored tile from self.pos.
		'''
        all_unexplored = self.find_all_unexplored()

        # Find distance of each tile
        distances = []
        for tile in all_unexplored:
            dist_x = abs(self.x - tile[0])
            dist_y = abs(self.y - tile[1])
            distances.append(dist_x + dist_y)

        # Find shortest distance
        min_i = -1
        min_dist = -1
        for i, dist in enumerate(distances):
            if min_dist is -1 or dist < min_dist:
                min_i = i
                min_dist = dist

        return all_unexplored[min_i]

    def find_oxygen_system(self):
        for coord in self.map:
            if self.map[coord] == 'O':
                return coord

        return None

    def find_max_dist_from_oxygen(self):
        start = self.find_oxygen_system()
        if start is None:
            print('Oxygen System not found')
            return None

        # Search for finish from start
        tile_list = [start]
        parents = {start: None}
        distances = {start: 0}

        while len(tile_list) > 0:
            tile = tile_list.pop(0)
            tile_x, tile_y = tile
            tile_dist = distances[tile]

            if tile not in self.map:
                continue

            # Add neighbors to list if not explored or smaller distance
            ## Up
            tile_up = tile_x, tile_y - 1
            if tile_up in parents:
                # Already searched tile. Check for shorter distance
                tile_up_dist = distances[tile_up]
                if tile_up_dist > tile_dist + 1:
                    if tile_up in self.map:
                        tile_list.append(tile_up)
                    parents[tile_up] = tile
                    distances[tile_up] = tile_dist + 1
            elif tile_up in self.map:
                # Nonsearched explored tile. Add to list if not a wall
                if self.map[tile_up] != '#':
                    tile_list.append(tile_up)
                    parents[tile_up] = tile
                    distances[tile_up] = tile_dist + 1
            else:
                # Nonsearched unexplored tile. Add to path but not the search list
                parents[tile_up] = tile
                distances[tile_up] = tile_dist + 1

            ## Down
            tile_down = tile_x, tile_y + 1
            if tile_down in parents:
                # Already searched tile. Check for shorter distance
                tile_down_dist = distances[tile_down]
                if tile_down_dist > tile_dist + 1:
                    if tile_down in self.map:
                        tile_list.append(tile_down)
                    parents[tile_down] = tile
                    distances[tile_down] = tile_dist + 1
            elif tile_down in self.map:
                # Nonsearched explored tile. Add to list if not a wall
                if self.map[tile_down] != '#':
                    tile_list.append(tile_down)
                    parents[tile_down] = tile
                    distances[tile_down] = tile_dist + 1
            else:
                # Nonsearched unexplored tile. Add to path but not the search list
                parents[tile_down] = tile
                distances[tile_down] = tile_dist + 1

            ## Left
            tile_left = tile_x - 1, tile_y
            if tile_left in parents:
                # Already searched tile. Check for shorter distance
                tile_left_dist = distances[tile_left]
                if tile_left_dist > tile_dist + 1:
                    if tile_left in self.map:
                        tile_list.append(tile_left)
                    parents[tile_left] = tile
                    distances[tile_left] = tile_dist + 1
            elif tile_left in self.map:
                # Nonsearched explored tile. Add to list if not a wall
                if self.map[tile_left] != '#':
                    tile_list.append(tile_left)
                    parents[tile_left] = tile
                    distances[tile_left] = tile_dist + 1
            else:
                # Nonsearched unexplored tile. Add to path but not the search list
                parents[tile_left] = tile
                distances[tile_left] = tile_dist + 1

            ## Right
            tile_right = tile_x + 1, tile_y
            if tile_right in parents:
                # Already searched tile. Check for shorter distance
                tile_right_dist = distances[tile_right]
                if tile_right_dist > tile_dist + 1:
                    if tile_right in self.map:
                        tile_list.append(tile_right)
                    parents[tile_right] = tile
                    distances[tile_right] = tile_dist + 1
            elif tile_right in self.map:
                # Nonsearched explored tile. Add to list if not a wall
                if self.map[tile_right] != '#':
                    tile_list.append(tile_right)
                    parents[tile_right] = tile
                    distances[tile_right] = tile_dist + 1
            else:
                # Nonsearched unexplored tile. Add to path but not the search list
                parents[tile_right] = tile
                distances[tile_right] = tile_dist + 1

        max_dist = 0
        for tile in distances:
            if distances[tile] > max_dist:
                max_dist = distances[tile]
        return max_dist

    def check_unexplored(self, coord):
        '''
		Returns a list of (x, y) coordinates containing unexplored tiles in 4 cardinal directions of given coordinate
		'''
        unexplored = []
        x, y = coord

        # Top
        tile_up = x, y - 1
        if tile_up not in self.map:
            unexplored.append(tile_up)
        # Bottom
        tile_down = x, y + 1
        if tile_down not in self.map:
            unexplored.append(tile_down)
        # Left
        tile_left = x - 1, y
        if tile_left not in self.map:
            unexplored.append(tile_left)
        # Right
        tile_right = x + 1, y
        if tile_right not in self.map:
            unexplored.append(tile_right)

        return unexplored

    def find_path_to_target(self, start, finish):
        # print('Finding path from %s to %s' % (start, finish))
        # Search for finish from start
        tile_list = [start]
        parents = {start: None}
        distances = {start: 0}

        while len(tile_list) > 0:
            tile = tile_list.pop(0)
            tile_x, tile_y = tile
            tile_dist = distances[tile]

            if tile not in self.map:
                continue

            # Add neighbors to list if not explored or smaller distance
            ## Up
            tile_up = tile_x, tile_y - 1
            if tile_up in parents:
                # Already searched tile. Check for shorter distance
                tile_up_dist = distances[tile_up]
                if tile_up_dist > tile_dist + 1:
                    if tile_up in self.map:
                        tile_list.append(tile_up)
                    parents[tile_up] = tile
                    distances[tile_up] = tile_dist + 1
            elif tile_up in self.map:
                # Nonsearched explored tile. Add to list if not a wall
                if self.map[tile_up] != '#':
                    tile_list.append(tile_up)
                    parents[tile_up] = tile
                    distances[tile_up] = tile_dist + 1
            else:
                # Nonsearched unexplored tile. Add to path but not the search list
                parents[tile_up] = tile
                distances[tile_up] = tile_dist + 1

            ## Down
            tile_down = tile_x, tile_y + 1
            if tile_down in parents:
                # Already searched tile. Check for shorter distance
                tile_down_dist = distances[tile_down]
                if tile_down_dist > tile_dist + 1:
                    if tile_down in self.map:
                        tile_list.append(tile_down)
                    parents[tile_down] = tile
                    distances[tile_down] = tile_dist + 1
            elif tile_down in self.map:
                # Nonsearched explored tile. Add to list if not a wall
                if self.map[tile_down] != '#':
                    tile_list.append(tile_down)
                    parents[tile_down] = tile
                    distances[tile_down] = tile_dist + 1
            else:
                # Nonsearched unexplored tile. Add to path but not the search list
                parents[tile_down] = tile
                distances[tile_down] = tile_dist + 1

            ## Left
            tile_left = tile_x - 1, tile_y
            if tile_left in parents:
                # Already searched tile. Check for shorter distance
                tile_left_dist = distances[tile_left]
                if tile_left_dist > tile_dist + 1:
                    if tile_left in self.map:
                        tile_list.append(tile_left)
                    parents[tile_left] = tile
                    distances[tile_left] = tile_dist + 1
            elif tile_left in self.map:
                # Nonsearched explored tile. Add to list if not a wall
                if self.map[tile_left] != '#':
                    tile_list.append(tile_left)
                    parents[tile_left] = tile
                    distances[tile_left] = tile_dist + 1
            else:
                # Nonsearched unexplored tile. Add to path but not the search list
                parents[tile_left] = tile
                distances[tile_left] = tile_dist + 1

            ## Right
            tile_right = tile_x + 1, tile_y
            if tile_right in parents:
                # Already searched tile. Check for shorter distance
                tile_right_dist = distances[tile_right]
                if tile_right_dist > tile_dist + 1:
                    if tile_right in self.map:
                        tile_list.append(tile_right)
                    parents[tile_right] = tile
                    distances[tile_right] = tile_dist + 1
            elif tile_right in self.map:
                # Nonsearched explored tile. Add to list if not a wall
                if self.map[tile_right] != '#':
                    tile_list.append(tile_right)
                    parents[tile_right] = tile
                    distances[tile_right] = tile_dist + 1
            else:
                # Nonsearched unexplored tile. Add to path but not the search list
                parents[tile_right] = tile
                distances[tile_right] = tile_dist + 1

        # Find path back to start
        new_path = []
        if finish in parents:
            path_node = finish
            while path_node != start:
                new_path.insert(0, path_node)
                path_node = parents[path_node]
            # print('Found Path: %s' % str(new_path))

        # print(new_path)
        return new_path

    def move_on_path(self):
        if self.path == []:
            print('Error: No Path to follow')
            return None
        path_x, path_y = self.path.pop(0)

        move_x = path_x - self.x
        move_y = path_y - self.y

        if move_y is -1 and move_x is 0:
            return 1
        elif move_y is 1 and move_x is 0:
            return 2
        elif move_y is 0 and move_x is -1:
            return 3
        elif move_y is 0 and move_x is 1:
            return 4
        else:
            print('%d, %d is invalid' % (move_x, move_y))
            return None

    def make_move(self):
        # move = -1
        # while move < 1 or move > 4:
        # 	move = int(input('Selection Direction: '))
        # return move

        if self.path == []:
            self.target = self.find_nearest_unexplored()
            self.path = self.find_path_to_target((self.x, self.y), self.target)

        move = self.move_on_path()

        return move

    def run(self):
        running = True
        while self.find_all_unexplored() != []:
            # self.print_map()

            # Give input and receive response
            move = self.make_move()
            # print('Move: %d' % move)
            self.computer.set_input([move])
            self.computer.execute_program()
            result = self.computer.get_last_value()

            # Find new position
            if move == 1:
                move_x = self.x
                move_y = self.y - 1
            elif move == 2:
                move_x = self.x
                move_y = self.y + 1
            elif move == 3:
                move_x = self.x - 1
                move_y = self.y
            elif move == 4:
                move_x = self.x + 1
                move_y = self.y

            # Update map bounds
            if move_x < self.min_x:
                self.min_x = move_x
            if move_x > self.max_x:
                self.max_x = move_x
            if move_y < self.min_y:
                self.min_y = move_y
            if move_y > self.max_y:
                self.max_y = move_y

            if result == 0:
                # Hit a wall
                if (move_x, move_y) not in self.map:
                    self.map[(move_x, move_y)] = '#'
            elif result == 1:
                # Moved in direction
                if (move_x, move_y) not in self.map:
                    self.map[(move_x, move_y)] = '.'
                self.x, self.y = move_x, move_y
            elif result == 2:
                # Found Oxygen System
                if (move_x, move_y) not in self.map:
                    self.map[(move_x, move_y)] = 'O'
                self.x, self.y = move_x, move_y
                running = False
            else:
                print('Error: Invalid result %d' % result)
                running = False

        oxygen_distance = self.find_max_dist_from_oxygen()
        print(oxygen_distance)
コード例 #4
0
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
コード例 #5
0
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)
コード例 #6
0
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))