Пример #1
0
class Droid:
    """ Executes the given intcode program, to navigate through damaged hull"""

    def __init__(self, intcode: List[int]):
        self.intcode = intcode
        self.result = []
        self.instruction = None

    def to_ascii(self, instruction: str) -> List[int]:
        ascii_instruction = [ord(char) for char in instruction]
        return ascii_instruction + [10]

    def get_input(self):
        try:
            value = next(self.instruction)
        except :
            self.instruction = (ascii_char for ascii_char in self.to_ascii(input()))
            value = next(self.instruction)
        return value

    def generate_output(self, value: int):
        try :
            self.result.append(chr(value))
        except:
            self.result.append(str(value))
        print(''.join(self.result))
    
    def execute(self):
        self.intcode_computer = IntcodeComputer(self.intcode, self.get_input, self.generate_output)
        while self.intcode_computer.has_next():
            next(self.intcode_computer.process_intcode())
Пример #2
0
class SpringDroid:
    """ Executes the given intcode program, to navigate through damaged hull"""

    def __init__(self, intcode: List[int]):
        self.intcode = intcode
        # Jum if :
        #   - 4 is ground
        #   - AND (1 empty or 2 empty or 3 empty)
        #   - AND (5 is ground or 8 is ground)
        self.program = ['NOT A T','NOT B J','OR J T','NOT C J','OR T J', 'AND D J', 'NOT E T','NOT T T', 'OR H T', 'AND T J', 'RUN']
        self.result = []
        self.instructions = (ascii_char for line in self.program for ascii_char in self.to_ascii(line) )

    def to_ascii(self, instruction: str) -> List[int]:
        ascii_instruction = [ord(char) for char in instruction]
        return ascii_instruction + [10]

    def get_input(self):
        return next(self.instructions)

    def generate_output(self, value: int):
        try :
            self.result.append(chr(value))
        except:
            self.result.append(str(value))
    
    def execute(self):
        self.intcode_computer = IntcodeComputer(self.intcode, self.get_input, self.generate_output)
        while self.intcode_computer.has_next():
            next(self.intcode_computer.process_intcode())
Пример #3
0
class Drone:
    """ Executes the given intcode program, to play a game"""

    def __init__(self, intcode: List[int]):
        self.intcode = intcode
        self.x = NotImplemented
        self.y = None
        self.give_x = True
        self.scanning = (None,None)
        self.current_position = (self.x, self.y)
        self.tractor_area = defaultdict(int)
        self.moves = {1: (0,1), 2:(0,-1), 4:(1,0), 3:(-1,0)}
        self.input_x = (x for point in zip(range(50), range(50)) for x in point)

    def get_input(self):
        print(f"Giving {self.x, self.y}") 
        if self.give_x:
            self.give_x = False
            return self.x
        else:
            self.give_x = True
            return self.y
    
    def generate_output(self, value: int):
        print(f"Got {value} on {self.x, self.y}")
        self.tractor_area[(self.x, self.y)] = value
    
    def execute(self):
        self.intcode_computer = IntcodeComputer(self.intcode, self.get_input, self.generate_output)
        while self.intcode_computer.has_next():
            next(self.intcode_computer.process_intcode())
    
    def execute_for_grid(self, max_x: int, max_y: int):
        for y in range(max_y):
            self.y = y
            for x in range(max_x):
                self.x = x
                self.execute()
    
    def curses_display(self, stdscr):
        stdscr.clear()
        stdscr.refresh()
        x,y = zip(*self.tractor_area.keys())
        xmin, xmax = min(x), max(x)
        ymin, ymax = min(y), max(y)
        for x in range(xmin, xmax + 1):
            for y in range(ymin, ymax + 1):
                block = self.tractor_area[(x,y)]
                character = "#" if block == 0 else "."
                stdscr.addstr(abs(x - xmin),abs(y - ymin), character) 
                stdscr.refresh()

    def command_line_display(self):
        x,y = zip(*self.tractor_area.keys())
        xmin, xmax = min(x), max(x)
        ymin, ymax = min(y), max(y)
        for y in range(ymin, ymax + 1):
            string = [f"{y:02d}"]
            for x in range(xmin, xmax + 1):
                if (x,y) not in self.tractor_area.keys():
                    print(f"Possible error at {x,y}")
                block = self.tractor_area[(x,y)]
                string.append('#' if block == 1 else '.')
            print(''.join(string))
Пример #4
0
class VacuumRobot:
    """ Executes the given intcode program, to play a game"""

    def __init__(self, intcode: List[int]):
        self.intcode = intcode
        self.x = 0
        self.y = 0
        self.current_position = (self.x, self.y)
        self.search_space = defaultdict(int)
        self.intcode_computer = IntcodeComputer(intcode, self.get_input, self.generate_output)
        self.moves = {1: (0,1), 2:(0,-1), 4:(1,0), 3:(-1,0)}
        self.alignment_points = []
        self.input = 1
        self.routine_index = 0
        self.main_rutine = [ord('A'), 44, ord('A'), 44, ord('B'), 44, ord('C'), 44, ord('B'), 44, ord('C'), 44, ord('B'), 44, ord('C'), 44, ord('B'), 44, ord('A'), 10]
        self.A = [ord('R'), 44, ord('6'), 44, ord('L'), 44, ord('1'), ord('2'), 44, ord('R'), 44, ord('6'), 10] 
        self.B = [ord('L'), 44, ord('1'), ord('2'), 44, ord('R'), 44, ord('6'), 44, ord('L'), 44, ord('8'), 44, ord('L'), 44, ord('1'), ord('2'), 10] 
        self.C = [ord('R'), 44, ord('1'), ord('2'), 44, ord('L'), 44, ord('1'), ord('0'), 44, ord('L'), 44, ord('1'), ord('0'), 10]
        self.video_feed = [110, 10]
        self.routines = self.A + self.B + self.C
        self.colllected_dust = []

    def get_input(self):
        if self.input == 1:
            value = self.main_rutine[self.routine_index]
            self.routine_index += 1
            if self.routine_index == len(self.main_rutine):
                self.routine_index = 0
                self.input = 2
            return value
        elif self.input == 2:
            value = self.routines[self.routine_index]
            self.routine_index += 1
            if self.routine_index == len(self.routines):
                self.routine_index = 0
                self.input = 3
            return value
        elif self.input == 3:
            value = self.video_feed[self.routine_index]
            self.routine_index += 1
            return value
        return 0
    
    def generate_output(self, value: int):
        self.colllected_dust.append(value)

    def get_alignments(self):
        for position, value in self.search_space.items():
            if value == 1 and len(self.valid_positions(position)) >= 3:
                logging.warning(f"Found alignment point at {position}")
                self.alignment_points.append(position)
    
    def get_alignments_value(self):
        return sum(x * y for x,y in self.alignment_points)

    def execute(self):
        while self.intcode_computer.has_next():
            next(self.intcode_computer.process_intcode())
    
    def next_position(self, mov, pos = None) -> Pos:
        if mov == 1:
            return (pos[0], pos[1] +1)
        elif mov == 2:
            return (pos[0], pos[1] -1)
        elif mov == 3:
            return (pos[0] + 1, pos[1])
        elif mov == 4:
            return (pos[0] - 1, pos[1])

    def next_robot_position(self, robot_pos, robot_orientation) -> Pos:
        if robot_orientation == 2:
            return (robot_pos[0], robot_pos[1] - 1)
        elif robot_orientation == 3:
            return (robot_pos[0] -1, robot_pos[1])
        elif robot_orientation == 4:
            return (robot_pos[0] + 1, robot_pos[1])
        elif robot_orientation == 5:
            return (robot_pos[0], robot_pos[1] + 1)

    def get_next_orientation(self, orientation, turn):
        if turn == 'L':
            if orientation == 2: return 3
            elif orientation == 3: return 5
            elif orientation == 4: return 2
            elif orientation == 5: return 4
        elif turn == 'R':
            if orientation == 2: return 4
            elif orientation == 3: return 2
            elif orientation == 4: return 5
            elif orientation == 5: return 3

    def valid_positions(self, pos):
        valid_pos = []
        for mov in self.moves.keys():
            next_cell = self.next_position(mov, pos)
            if next_cell in self.search_space.keys() and self.search_space[next_cell] == 1:
                valid_pos.append(next_cell)
        return valid_pos
    
    def curses_display(self, stdscr):
        stdscr.clear()
        stdscr.refresh()
        x,y = zip(*self.search_space.keys())
        xmin, xmax = min(x), max(x)
        ymin, ymax = min(y), max(y)
        for x in range(xmin, xmax + 1):
            for y in range(ymin, ymax + 1):
                block = self.search_space[(x,y)]
                character = "#" if block == 0 else "."
                stdscr.addstr(abs(x - xmin),abs(y - ymin), character) 
                stdscr.refresh()

    def greedy_solver(self):
        robot_pos = self.robot_pos
        robot_orientation = 2
        total_scaffold = sum(v for v in self.search_space.values() if v == 1)
        print(f"Total scaffold to cover {total_scaffold}")
        covered = 0
        movements = []
        while covered < total_scaffold:
            avance = 0
            next_robot_pos = self.next_robot_position(robot_pos, robot_orientation)
            while self.search_space[next_robot_pos] == 1:
                avance += 1
                robot_pos = next_robot_pos
                next_robot_pos = self.next_robot_position(robot_pos, robot_orientation)
            print(f"Advanced {avance}, covered {covered}")
            avance += 1
            movements.append(avance)
            covered += avance
            avance = 0
            next_robot_orientation = self.get_next_orientation(robot_orientation, 'L')
            next_robot_pos = self.next_robot_position(robot_pos, next_robot_orientation)
            if self.search_space[next_robot_pos] == 1:
                robot_pos = next_robot_pos
                robot_orientation = next_robot_orientation
                movements.append('L')
                print(f"Turning left")
            else:
                next_robot_orientation = self.get_next_orientation(robot_orientation, 'R')
                next_robot_pos = self.next_robot_position(robot_pos, next_robot_orientation)
                if self.search_space[next_robot_pos] == 1:
                    robot_pos = next_robot_pos
                    robot_orientation = next_robot_orientation
                    movements.append('R')
                    print(f"Turning right")
                else:
                    raise("Dead end")
        return movements

    def command_line_display(self):
        x,y = zip(*self.search_space.keys())
        xmin, xmax = min(x), max(x)
        ymin, ymax = min(y), max(y)
        for y in range(ymin, ymax + 1):
            string = [f"{y:02d}"]
            for x in range(xmin, xmax + 1):
                if (x,y) not in self.search_space.keys():
                    print(f"Possible error at {x,y}")
                block = self.search_space[(x,y)]
                if (x,y) in self.alignment_points:
                    string.append('O')
                elif block == 2:
                    string.append('>')
                else: 
                    string.append("#" if block == 1 else ".")
            print(''.join(string))
Пример #5
0
class Drone:
    """ Executes the given intcode program, to play a game"""
    def __init__(self, intcode: List[int]):
        self.intcode = intcode
        self.current_position = (0, 0)
        self.search_space = defaultdict(int)
        self.search_space[self.current_position] = -1
        self.unvisited_nodes = set()
        self.explored = defaultdict(int)
        self.solution_path = []
        self.image = None
        self.intcode_computer = IntcodeComputer(intcode, self.get_input,
                                                self.generate_output)
        self.moves = {1: (0, 1), 2: (0, -1), 4: (1, 0), 3: (-1, 0)}

    def get_input(self):
        return self.input

    def generate_output(self, value: int):
        print(f"Got {value}")
        temptative_positon = self.next_position(self.input)
        self.search_space[temptative_positon] = value
        if value != 0:
            self.current_position = temptative_positon

    def execute(self):
        while self.intcode_computer.has_next():
            next(self.intcode_computer.process_intcode())

    def next_position(self, mov) -> Pos:
        if mov == 1:
            return (self.current_position[0], self.current_position[1] + 1)
        elif mov == 2:
            return (self.current_position[0], self.current_position[1] - 1)
        elif mov == 3:
            return (self.current_position[0] + 1, self.current_position[1])
        elif mov == 4:
            return (self.current_position[0] - 1, self.current_position[1])

    def step_back(self):
        # Remove step from solution path
        print(f"Found dead end, stepping back from {self.current_position}")
        last_move = self.solution_path.pop()
        # Undo step
        if last_move == 1:
            self.input = 2
        elif last_move == 2:
            self.input = 1
        elif last_move == 3:
            self.input = 4
        elif last_move == 4:
            self.input = 3
        self.intcode_computer.step()

    def step_forward(self, mov) -> bool:
        self.input = mov
        self.solution_path.append(mov)
        self.intcode_computer.step()

    def explore(self, mov, next_pos):
        print(f"Trying {mov} from {self.current_position}")
        self.step_forward(mov)
        if self.search_space[next_pos] == 2:
            print(
                f"Solution found at {next_pos} in {len(self.solution_path)} steps"
            )
            print(self.solution_path)
            self.display_screen()
            return True
        elif self.search_space[next_pos] == 0:
            # Hit a wall, remove step from solution path
            self.solution_path.pop()
            return False
        else:
            self.explored[self.current_position] = 1
            for mov in self.moves.keys():
                next_pos = self.next_position(mov)
                if self.explored[next_pos] == 0:
                    found = self.explore(mov, next_pos)
                    if found:
                        return True
            self.step_back()
            return False

    def command_line_display(self, image):
        for x in range(image.shape[0]):
            string = []
            for y in range(image.shape[1]):
                if image[x, y] == -1:
                    string.append('@')
                if image[x, y] == 0:
                    string.append('#')
                if image[x, y] == 1:
                    string.append('X')
                if image[x, y] == 2:
                    string.append('*')
                if image[x, y] == 3:
                    string.append('.')
            print(''.join(string))

    def display_screen(self):
        # if self.image is None:
        self.min_x = min(key[0] for key in self.search_space.keys())
        max_x = max(key[0] for key in self.search_space.keys())
        min_y = min(key[1] for key in self.search_space.keys())
        self.max_y = max(key[1] for key in self.search_space.keys())

        size_x = max_x - self.min_x
        size_y = self.max_y - min_y

        self.image = np.ones(shape=(size_y + 1, size_x + 1)) * 3
        for position, color in self.search_space.items():
            # Correct coordinates. In the array (0,0) is top left
            if position == (0, 0): color = -1
            self.image[abs(position[1] - self.max_y),
                       abs(position[0] - self.min_x)] = color
        self.command_line_display(self.image)
Пример #6
0
class Arcade:
    """ Executes the given intcode program, to play a game"""

    def __init__(self, intcode: List[int]):
        self.intcode = intcode
        self.saves = []
        self.current_position = (0, 0)
        self.screen = defaultdict(int)
        self.intcode_computer = IntcodeComputer(intcode, self.get_input, self.generate_output)
        self.offset = 0
        self.score = 1
        self.image = None
    
    def get_input(self):
        os.system('clear')
        print(f"CURENT SCORE: {self.score}")
        self.display_screen()
        c = None
        while c not in ('-1','1', '0'):
            c = sys.stdin.read(1)
            if c == '-':
                c += sys.stdin.read(1)
            if c == '2':
                print(f"Saving game..")
                with open (f'saves/{self.score}.save', 'wb') as f:
                    pickle.dump(self.intcode_computer, f)
            if c == '3':
                c = '-1'
        return int(c)
    
    def generate_output(self, value: int):
        if self.offset == 0:
            self.x = value
            self.offset += 1
        elif self.offset == 1:
            self.y = value
            self.offset += 1
        elif self.offset == 2:
            if self.x == -1 and self.y == 0:
                logging.info(f"Setting score to {value}")
                print(f"Setting score to {value}")
                self.score = value
            else:
                logging.info(f"Setting tile in {self.x},{self.y} with {value}")
                self.screen[(self.x,self.y)] = value
            self.offset = 0  
    
    def load_save(self):
        print(f"Want to load save?")
        go_back = input()
        if go_back != '3':
            print(self.score)
            print("Loading save")
            with open(f"saves/{go_back}.save", 'rb') as f:
                self.intcode_computer = pickle.load(f)

    def execute(self):
        self.load_save()
        while True:
            try:
                self.current_computer = next(self.intcode_computer.process_intcode())
                if self.current_computer is None:
                    print(self.score)
                    return
            except:
                print(self.score)
                self.load_save()

    def command_line_display(self, image):
        for x in range(image.shape[0]):
            string = []
            for y in range(image.shape[1]):
                if image[x,y] == 0:
                    string.append('.')
                if image[x,y] == 1:
                    string.append('|')
                if image[x,y] == 2:
                    string.append('#')
                if image[x,y] == 3:
                    string.append('=')
                if image[x,y] == 4:
                    string.append('*')
            print(''.join(string))

    def display_screen(self):
        if self.image is None:
            self.min_x = min(key[0] for key in self.screen.keys())
            max_x = max(key[0] for key in self.screen.keys())
            min_y = min(key[1] for key in self.screen.keys())
            self.max_y = max(key[1] for key in self.screen.keys())

            size_x = max_x - self.min_x
            size_y = self.max_y - min_y

            self.image = np.zeros(shape=(size_y + 1, size_x + 1))
        for position,color in self.screen.items():
            # Correct coordinates. In the array (0,0) is top left
            self.image[abs(position[1] - self.max_y), abs(position[0] - self.min_x)] = color
        self.command_line_display(self.image)
Пример #7
0
class Drone:
    """ Executes the given intcode program, to play a game"""
    def __init__(self, intcode: List[int]):
        self.intcode = intcode
        self.x = 0
        self.y = 0
        self.give_x = True
        self.tractor_area = defaultdict(int)

    def get_input(self):
        # print(f"Giving {self.x, self.y}")
        if self.give_x:
            self.give_x = False
            return self.x
        else:
            self.give_x = True
            return self.y

    def generate_output(self, value: int):
        # print(f"Got {value} on {self.x, self.y}")
        self.tractor_area[(self.x, self.y)] = value

    def execute(self):
        self.intcode_computer = IntcodeComputer(self.intcode, self.get_input,
                                                self.generate_output)
        while self.intcode_computer.has_next():
            next(self.intcode_computer.process_intcode())

    def manual_execute(self):
        user_input = input().split()
        self.x, self.y = int(user_input[0]), int(user_input[1])
        while self.x != 'q':
            self.intcode_computer = IntcodeComputer(self.intcode,
                                                    self.get_input,
                                                    self.generate_output)
            while self.intcode_computer.has_next():
                next(self.intcode_computer.process_intcode())
            user_input = input().split()
            self.x, self.y = int(user_input[0]), int(user_input[1])

    def find_first_one_in_line(self, line: int):
        start = 1
        found = False
        end = line
        self.y = line
        while not found:
            self.x = start + (end - start) // 2 + 1
            self.execute()
            if self.tractor_area[(self.x, self.y)] == 1:
                self.x -= 1
                self.execute()
                if self.tractor_area[(self.x, self.y)] == 0:
                    # print(f"Found at {self.x,self.y}")
                    found = True
                end = self.x
            else:
                start = self.x
        return self.x + 1

    def check_santa_ship_fit(self, x, y, ship_len):
        self.y = self.y - ship_len + 1
        self.x = x + ship_len - 1
        self.execute()
        return self.tractor_area[(self.x, self.y)] == 1

    def search_first_len(self, ship_len):
        # Try line Y
        # Find first 1 in line Y
        # Check if 100 above is also 1, check if 100 right is also one
        start = ship_len
        end = None
        end_found = False
        found = False
        candidate_x = None
        candidate_y = None
        while not found:
            if not end_found:
                self.y = start * 2
            else:
                self.y = start + (end - start) // 2 + 1
            print(f" **** Trying y={self.y} ****")
            first_x_one = self.find_first_one_in_line(self.y)
            candidate_y = self.y
            candidate_x = first_x_one
            print(f"first 1 in line {self.y}: {first_x_one}")
            if self.check_santa_ship_fit(first_x_one, self.y, ship_len):
                print(
                    f" **** Found candidate at x={first_x_one} y={candidate_y} ****"
                )
                end_found = True
                found = True
                end = candidate_y
                for i in range(1, 2):
                    first_x_one = self.find_first_one_in_line(candidate_y - i)
                    if not self.check_santa_ship_fit(
                            first_x_one, candidate_y - 1, ship_len):
                        pass
                    else:
                        print(
                            f"***** Counter at {first_x_one,candidate_y- i} ******"
                        )
                        found = False
                if found == True:
                    print(f"***** Found at {candidate_x,candidate_y} ******")

            else:
                start = candidate_y
        return candidate_x, candidate_y - ship_len + 1

    def execute_for_grid(self, max_x: int, max_y: int):
        for y in range(max_y):
            self.y = y
            for x in range(max_x):
                self.x = x
                self.execute()

    def command_line_display(self):
        x, y = zip(*self.tractor_area.keys())
        xmin, xmax = min(x), max(x)
        ymin, ymax = min(y), max(y)
        for y in range(ymin, ymax + 1):
            string = [f"{y:02d}"]
            for x in range(xmin, xmax + 1):
                if (x, y) not in self.tractor_area.keys():
                    print(f"Possible error at {x,y}")
                block = self.tractor_area[(x, y)]
                string.append('#' if block == 1 else '.')
            print(''.join(string))