示例#1
0
class robot:
    '''
    This robot paints panels. It starts on panel (0,0) which is either black (0) or white (1).
    Then it asks the Intcode computer for input. This returns the color to paint the current panel and the direction to take.
    The robot will keep moving and painting until the Intcode computer is done running the input code.
    '''
    def __init__(self, start_c):

        self.dir = np.array(
            (1, 0))  #Left: (0,-1), Down: (-1,0), Right: (0,1), Up: (1,0)
        self.panels = {}
        self.panels[(0, 0)] = start_c  #Start on panel that is black or white
        self.cur_pos = np.array((0, 0))
        self.brain = Intcode(input_code)

        self.anti_clockwise = {
            (-1, 0): (0, -1),
            (0, -1): (1, 0),
            (1, 0): (0, 1),
            (0, 1): (-1, 0)
        }
        self.clockwise = {
            (-1, 0): (0, 1),
            (0, 1): (1, 0),
            (1, 0): (0, -1),
            (0, -1): (-1, 0)
        }

    def next_instruction(self):

        return self.brain.RunIntcode([self.cur_color])

    def paint(self, c):

        self.panels[tuple(self.cur_pos)] = c

    def move(self, d):

        if d == 0:  #Anti-clockwise (turn 90 degrees left)
            self.dir = np.array(self.anti_clockwise[tuple(self.dir)])
        elif d == 1:  #turn 90 degrees right
            self.dir = np.array(self.clockwise[tuple(self.dir)])
        else:
            raise Exception('Invalid direction encountered.')

        #Update position based on this direction
        self.cur_pos = self.cur_pos + self.dir
        if tuple(self.cur_pos) not in self.panels:
            self.panels[tuple(self.cur_pos)] = 0  #Initiate this panel to black

        self.cur_color = self.panels[tuple(self.cur_pos)]

    def run(self):

        self.cur_color = self.panels[tuple(
            self.cur_pos)]  #0 is black, 1 is white

        next_inst = self.next_instruction()

        while len(next_inst) != 0:

            c, d = next_inst  #Color to paint and direction to turn
            self.paint(c)
            self.move(d)

            next_inst = self.next_instruction()

    def paint_panels(self):

        #Paint the panels on a grid and show result

        all_y = [a[0] for a in self.panels.keys()]
        all_x = [a[1] for a in self.panels.keys()]

        min_x = np.min(all_x)
        max_x = np.max(all_x)
        diff_x = max_x - min_x + 1

        min_y = np.min(all_y)
        max_y = np.max(all_y)
        diff_y = max_y - min_y + 1

        grid = np.zeros((diff_y, diff_x))
        for i, y_i in enumerate(range(min_y, max_y + 1)):
            row = []
            for x_i in range(min_x, max_x + 1):
                if (y_i, x_i) in self.panels:
                    row.append(self.panels[(y_i, x_i)])
                else:
                    row.append(0)

            grid[i, :] = row

        plt.imshow(grid.T, origin='lower')
        plt.savefig('./Day11/message.png')
示例#2
0
class droid:

    '''
    Droid class that will explore the maze.
    '''

    def __init__(self):

        self.cur_pos = np.array([0,0]) #Current position of the droid (2D coordinate)
        self.game = Intcode(input_code)

        #north (1), south (2), west (3), and east (4)
        self.in_to_dirs = {1:tuple([1,0]), 2:tuple([-1,0]), 3:tuple([0,-1]), 4:tuple([0,1])}
        self.dirs_to_in = {tuple(v): int(k) for k, v in self.in_to_dirs.items()} #Reverse dictionary

        self.unexplored = [] #Buffer list for unexplored tiles adjacent to original position 

        self.anti_clockwise = {1:3, 3:2, 2:4, 4:1}
        self.clockwise = {1:4, 4:2, 2:3, 3:1}
        self.reverse_dir = {1:2, 2:1, 3:4, 4:3}

        #0 = wall, 1=empty, 2=oxygen
        self.panels = {tuple(self.cur_pos): 0} #Panels of which we know the identity
        self.grid_num = 0 #counter for plots

    def move(self, dir):

        #Move in direction north (1), south (2), west (3), and east (4).

        output = self.game.RunIntcode([dir]) #Gives back 0 for wall, 1 for open space, 2 for oxygen system in list of length 1
        
        assert len(output) == 1
        
        return output[0]
    
    def test_move(self, dir):

        #Test a move but do not actually move there (so move droid back to original position)

        output = self.game.RunIntcode([dir]) #Move in dir

        assert len(output) == 1

        if output[0] != 0: #If it was not a wall, move back (if it was a wall droid is still in original position)
            revdir = self.reverse_dir[dir]
            self.game.RunIntcode([revdir]) #move back

        return output

    def fill_unexplored(self):

        for r in [1,2,3,4]: #Check every direction
            possible_next = self.cur_pos + np.array(self.in_to_dirs[r])
            if tuple(possible_next) not in self.panels:
                self.unexplored.append(tuple(possible_next))

    def explore(self):

        #Returns a list of possible next positions from self.cur_pos

        self.fill_unexplored() #Get surrounding unexplored positions
        possible_next = []

        while len(self.unexplored) != 0: #As long as there are unexplored surrounding positions to go to

            next_pos = np.array(self.unexplored.pop())

            input_dir = self.dirs_to_in[tuple(next_pos - self.cur_pos)]

            out = self.test_move(input_dir)[0] #Check what's at the position

            if out == 0: #not moved, destination was a wall
                self.panels[tuple(next_pos)] = 0.5 #WALL
            elif out == 1: #moved to position
                possible_next.append(next_pos)
            elif out == 2: #moved to position, oxygen system is here
                possible_next.append(next_pos)
        
        return possible_next

    def show_grid(self, save=False):

        #Convert coordinates to only positive numbers
        y_map = np.arange(-19, 22) #-19 - 21, 41 numbers
        x_map = np.arange(-21, 20) #-21 - 20, 41 numbers

        grid = np.zeros((41,41))

        for i in range(grid.shape[0]):
            row = np.zeros(grid.shape[1])

            for k in self.panels.keys():

                if int(np.where(y_map == k[0])[0]) == i:
                    row[int(np.where(x_map == k[1])[0])] = self.panels[k]
            
            grid[i,:] = row

        plt.xticks([])
        plt.yticks([])

        plt.imshow(grid, origin='lower', vmin=0, vmax=3, cmap='Greys')


        if save:
            plt.savefig('./Day15/grids/'+str(self.grid_num)+'.png', format="png")
            plt.clf()
            self.grid_num+=1
        else:
            plt.show()
    
    def run(self):

        path_taken = LifoQueue()
        path_taken.put(self.cur_pos)
        split_points = [] #Coordinates from which two or more directions can be taken
        counter = 0

        while not path_taken.empty():

            counter+=1
            if counter % 10 == 0:
                print('Counter: {}'.format(counter))

            pn = self.explore()

            if len(pn) > 1: #More than 1 unexplored path to take
                split_points.append(tuple(self.cur_pos))

                next_pos = pn.pop()
                output = self.move(self.dirs_to_in[tuple(next_pos - self.cur_pos)])

                if output == 1:
                    self.panels[tuple(next_pos)] = 1
                elif output == 2:
                    self.panels[tuple(next_pos)] = 2
                
                self.cur_pos = next_pos
                path_taken.put(tuple(self.cur_pos))
            
            elif len(pn) == 1: #One unexplored path to take

                next_pos = pn.pop()
                output = self.move(self.dirs_to_in[tuple(next_pos - self.cur_pos)])

                if output == 1:
                    self.panels[tuple(next_pos)] = 1
                elif output == 2:
                    self.panels[tuple(next_pos)] = 2

                self.cur_pos = next_pos
                path_taken.put(tuple(self.cur_pos))
            
            else: #Need to go back to split point

                last_step = self.cur_pos
                while (tuple(last_step) not in split_points) & (not path_taken.empty()):

                    last_step = path_taken.get()

                    #If previous position not the same as current position, move back to previous position
                    if tuple(np.array(last_step) - np.array(self.cur_pos)) != (0,0): 
                        input_dir = self.dirs_to_in[tuple(np.array(last_step) - np.array(self.cur_pos))]
                        out = self.move(input_dir)
                        self.cur_pos = last_step

                if not path_taken.empty():
                    path_taken.put(last_step)
                    split_points.remove(last_step)
                    self.cur_pos = last_step
示例#3
0
import numpy as np
from Intcode import *
from itertools import permutations

with open("./Day9/input.txt") as file:
    input_code = [int(s) for s in file.read().strip().split(',')]

IntComputer1 = Intcode(input_code)
answer_part1 = IntComputer1.RunIntcode([1])[0]
IntComputer2 = Intcode(input_code)
answer_part2 = IntComputer2.RunIntcode([2])[0]

print('Answer part 1: {}'.format(answer_part1))
print('Answer part 2: {}'.format(answer_part2))