Esempio n. 1
0
def main(stdscr):
    # Clear screen
    stdscr.clear()

    curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLACK)
    curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK)

    input_queue = Queue()
    output_queue = Queue()

    program = IntcodeProgram(io_scheme=IntcodeProgram.IOScheme.QUEUE,
                             input_queue=input_queue,
                             output_queue=output_queue)
    program.initialize_memory_from_file('input.txt')

    droid = RepairDroid()
    program.queue_input(droid.movement)

    while not droid.at_o2_system:
        try:
            program.execute_next()

        except WaitingForInput:
            droid.process_program_outcome(program)
            droid.draw_map(stdscr)

    o2_system = droid.position

    droid.draw_map(stdscr, message=f'O2 System at {o2_system}')
    stdscr.getch()

    shortest_path = astar(droid.path_map, Point(0, 0), o2_system)

    droid.draw_map(stdscr,
                   draw_path=shortest_path,
                   message=f'Part One: {len(shortest_path) - 1}')
    stdscr.getch()

    while droid.path_unseen:
        try:
            program.execute_next()

        except WaitingForInput:
            droid.process_program_outcome(program)
            droid.draw_map(stdscr)

    droid.draw_map(stdscr, message=f'end map')
    stdscr.getch()

    all_paths = astar(droid.path_map, o2_system, Point(1000, 1000))
    max_depth = max(all_paths, key=lambda x: x.g)

    longest_path = astar(droid.path_map, o2_system, max_depth.position)
    droid.draw_map(stdscr, message=f'end map', draw_path=longest_path)
    droid.draw_map(stdscr,
                   draw_path=longest_path,
                   message=f'Part Two: {len(longest_path) - 1}')
    stdscr.getch()
Esempio n. 2
0
def main():
    input_queue = Queue()
    output_queue = Queue()
    program = IntcodeProgram(io_scheme=IntcodeProgram.IOScheme.QUEUE,
                             input_queue=input_queue,
                             output_queue=output_queue)
    program.initialize_memory_from_file('input.txt')
    memory_dump = program.dump_memory()

    survey_hull(program, memory_dump)
    survey_hull(program, memory_dump, run=True)
Esempio n. 3
0
def d2p2():
    prod = product(range(100), range(100))
    result = None
    for noun, verb in prod:
        ip = IntcodeProgram(d2_input)
        ip.intcode[1], ip.intcode[2] = noun, verb
        while not ip.halted:
            ip.next()
            if ip.intcode[0] == 19690720:
                result = int(str(noun).zfill(2) + str(verb).zfill(2))
                break
    return result
Esempio n. 4
0
def count_blocks(inputs, display=False, debug=False):
    '''Executes the Intcode program on the provided inputs and finds out the
    number of blocks on the screen when the game exits. It also returns the
    board when the game exits (i.e. the initial board since no game was
    actually played).
    
    :param inputs: List of integers to execute as an Intcode program.
    :type inputs: list(int)
    :param display: Whether or not to display the board after the game exits.
    :type display: bool
    :param debug: Whether or not the IntcodeProgram should debug its
        execution at each instruction processing.
    :type debug: bool
    :return: Inital board (when no game was played) and number of blocks on the
        screen when the game exits.
    :rtype: dict, int
    '''
    # prepare the board
    board = {}
    # prepare the program instance to read the given inputs as an Intcode
    # program
    program = IntcodeProgram(inputs, debug=debug)
    running = True
    # execute the program until it halts (but pause every 3 outputs)
    while running:
        # execute until 3 digits have been outputted
        state = program.run(pause_every=3)
        # check for state:
        # . if paused: parse outputs and apply the actions
        if state == 'pause':
            x, y, id = program.output
            program.reset_output()
            if id == 0:
                marker = None
            elif id == 1:
                marker = 'W'
            elif id == 2:
                marker = 'B'
            elif id == 3:
                marker = 'H'
            else:
                marker = 'O'
            board[(x, y)] = marker
        # . else: stop the program
        elif state is None:
            running = False
            break

    if display:
        display_board(board)

    return board, sum([1 if m == 'B' else 0 for m in board.values()])
Esempio n. 5
0
def main():
    input_queue = Queue()
    output_queue = Queue()
    program = IntcodeProgram(io_scheme=IntcodeProgram.IOScheme.QUEUE,
                             input_queue=input_queue,
                             output_queue=output_queue)
    program.initialize_memory_from_file('input.txt')
    memory_dump = program.dump_memory()

    left_edge_coordinates, right_edge_coordinates = part_one(
        program, memory_dump)
    part_two(program, memory_dump, left_edge_coordinates,
             right_edge_coordinates)
Esempio n. 6
0
def find_pair(inputs, wanted_output):
    '''A brute-force algorithm to systematically try all possible input pairs
    until we find the one that gave the desired output (we can determine a
    finished set of possible candidates since we know that each number is in the
    [0, 99] range).
    
    :param inputs: List of integers to execute as an Intcode program.
    :type inputs: list(int)
    :param wanted_output: Desired output of the program.
    :type wanted_output: int
    :return: Specific checksum that matches the desired output.
    :rtype: int
    '''
    # prepare program
    program = IntcodeProgram(inputs)
    for noun in range(0, 100):  # range is [0, 100[ = [0, 99]
        for verb in range(0, 100):
            # reset program to initial state
            program.reset()
            # set up noun and verb
            program.program[1] = noun
            program.program[2] = verb
            # run and compare result
            program.run()
            if program.program[0] == wanted_output:
                return 100 * noun + verb
Esempio n. 7
0
def get_map(inputs, display=False, debug=False):
    '''Executes the Intcode program on the provided inputs and finds out the
    required number of moves to reach the oxygen system in the room.
    
    :param inputs: List of integers to execute as an Intcode program.
    :type inputs: list(int)
    :param display: Whether or not to display the map at the end of the scan.
    :type display: bool
    :param debug: Whether or not the IntcodeProgram should debug its
        execution at each instruction processing.
    :type debug: bool
    :return: Current map of the scaffolds and simplified map.
    :rtype: list(str), dict(tuple(int, int), int)
    '''
    # prepare the program instance to read the given inputs as an Intcode
    # program
    program = IntcodeProgram(inputs, debug=debug)
    # run the program to get the current map
    program.run()
    map = [chr(x) for x in program.output]

    # get simple map with only the coordinates of the scaffolds and of the robot
    # (ignore empty space)
    simple_map = {}
    # . get map (width, height) dimensions
    w = map.index('\n')
    h = len(map) // w
    # . remove new lines from map to avoid offset
    m = [item for item in map if item != '\n']
    for y in range(h):
        for x in range(w):
            v = m[x + y * w]
            if v == '#':
                simple_map[(x, y)] = 1
            elif v == '^':
                simple_map[(x, y)] = 2
            elif v == '>':
                simple_map[(x, y)] = 3
            elif v == 'v':
                simple_map[(x, y)] = 4
            elif v == '<':
                simple_map[(x, y)] = 5

    # optionally display the map
    if display:
        display_map(map)

    return map, simple_map
Esempio n. 8
0
def find_oxygen_system(inputs, display=False, export=False, debug=False):
    '''Executes the Intcode program on the provided inputs and finds out the
    required number of moves to reach the oxygen system in the room.
    
    :param inputs: List of integers to execute as an Intcode program.
    :type inputs: list(int)
    :param display: Whether or not to display the board at the end.
    :type display: bool
    :param export: Whether or not to export the board at each iteration of
        exploration and path building.
    :type export: bool
    :param debug: Whether or not the IntcodeProgram should debug its
        execution at each instruction processing.
    :type debug: bool
    :return: MazeSolver instance and number of moves required to reach the
        oxygen system (i.e. length of the shortest path to the system).
    :rtype: MazeSolver, int
    '''
    # prepare the program instance to read the given inputs as an Intcode
    # program
    program = IntcodeProgram(inputs, debug=debug)
    # prepare and run the maze solver to explore the maze fully
    solver = MazeSolver(program, export=export, export_size=(41, 41))
    solver.explore()
    # use Dijkstra's algorithm to get the shortest path between the start
    # position of the robot and the target position (position of the oxygen
    # system)
    path = solver.find_shortest_path()
    # optionally print the board and the shortest path
    if display:
        solver.print_board(path)
    return solver, len(path) - 1  # remove 1 for the start position
Esempio n. 9
0
def process_inputs(inputs):
    '''Executes the Intcode program on the provided inputs and computes the final
    result. Here, we use the [0, 4] phase settings range and no feedback loop
    (so we only go through the amplifiers chain once).
    
    :param inputs: List of integers to execute as an Intcode program.
    :type inputs: list(int)
    :return: Maximum input to the thrusters.
    :rtype: int
    '''
    # prepare all possible permutations for phase settings:
    # we have X possibilities for the first one, X-1 for the second one,
    # X-2 for the third one... (no replacement)
    n_amplifiers = 5
    candidate_phase_settings = itertools.permutations(range(5), n_amplifiers)
    thrusts = []
    
    IntcodeProgram.INSTANCE_ID = 0 # reset global instances IDs
    amplifiers = [ IntcodeProgram(inputs) for _ in range(n_amplifiers) ]    
    for phase_settings in candidate_phase_settings:
        # reset all amplifiers
        for amp in amplifiers:
            amp.reset()
        # prepare input for first amplifier
        amplifiers[0].push_memory(0)
        for current_amplifier in range(n_amplifiers):
            phase = phase_settings[current_amplifier]
            amplifiers[current_amplifier].check_running(phase)
            # execute program
            amplifiers[current_amplifier].run_multiple(amplifiers)
        # remember the power sent to the thrusters with these settings
        output = amplifiers[current_amplifier].output[-1]
        thrusts.append(output)
    return max(thrusts)
Esempio n. 10
0
 def __init__(self, master, memory, **kwargs):
     self.master = master
     self.scale = 10
     self.width = 500
     self.height = 500
     self.canvas = tk.Canvas(
         self.master,
         width=self.width,
         height=self.height,
         bg='#333'
     )
     self.canvas.pack()
     first_droid = Droid(self, IntcodeProgram(memory), [(0, 0)])
     self.droids = OrderedDict()
     self.droids[first_droid.id] = first_droid
     self.oxygens = OrderedDict()
     self.wall_mapping = {}
     self.oxygen_mapping = {}
     self.moves = [1, 2, 3, 4]
     self.move_offset = {
         1: lambda p: (p[0], p[1]-1),
         2: lambda p: (p[0], p[1]+1),
         3: lambda p: (p[0]-1, p[1]),
         4: lambda p: (p[0]+1, p[1])
     }
     self.oxygen_mode = False
     self.oxygen_start = None
     self.master.after(0, self.refresh)
Esempio n. 11
0
def find_closest_square(inputs, square_size):
    '''Executes the Intcode program on the provided inputs and searches for the
    closet square of given size that fits in the tractor beam. Returns a custom
    checksum for its top-left corner coordinate.
    
    :param inputs: List of integers to execute as an Intcode program.
    :type inputs: list(int)
    :param square_size: Size of the edge of the square to find in the grid.
    :type square_size: int
    :return: Top-left corner coordinate checksum.
    :rtype: int
    '''
    # prepare the program instance to read the given inputs as an Intcode
    # program
    program = IntcodeProgram(inputs)
    # get a large grid to inspect
    size = 2000
    map = get_map(program, size)

    # find a square in it... if possible!
    # (else, retry with a larger size)
    candidates = set()
    for position in map:
        x, y = position
        if ((x, y + square_size - 1)) in map and \
            ((x + square_size - 1, y)) in map and \
            ((x + square_size - 1, y + square_size - 1)) in map:
            candidates.add((x, y))
    if len(candidates) > 0:
        square = sorted(candidates, key=lambda x: x[0] * 10000 + x[1])[0]
    else:
        return -1
    # compute checksum of square
    return square[0] * 10000 + square[1]
Esempio n. 12
0
def get_affected_positions(inputs, display=False, debug=False):
    '''Executes the Intcode program on the provided inputs and checks how many
    positions on the grid are affected by the tractor beam.
    
    :param inputs: List of integers to execute as an Intcode program.
    :type inputs: list(int)
    :param display: Whether or not to display the grid at the end of the scan.
    :type display: bool
    :param debug: Whether or not the IntcodeProgram should debug its
        execution at each instruction processing.
    :type debug: bool
    :return: Number of positions affected by the tractor beam.
    :rtype: int
    '''
    # prepare the program instance to read the given inputs as an Intcode
    # program
    program = IntcodeProgram(inputs)
    # get the map of 50x50
    map = get_map(program, 50)

    # optionally display the map
    if display:
        for y in range(50):
            row = ''
            for x in range(50):
                row += '#' if (x, y) in map else '.'
            print(row)

    return len(map)
Esempio n. 13
0
def make_tests():
    '''Performs tests on the provided examples to check the result of the
    computation functions is ok.'''
    # test new instructions
    ref = '109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99'
    program = IntcodeProgram([
        109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0,
        99
    ])
    program.run()
    assert ','.join([str(x) for x in program.output]) == ref

    # Part I + II
    assert len(str(process_inputs([1102, 34915192, 34915192, 7, 4, 7, 99,
                                   0]))) == 16
    assert process_inputs([104, 1125899906842624, 99]) == 1125899906842624
Esempio n. 14
0
def process_inputs(inputs, restore_gravity_assist=False):
    '''Executes the Intcode program on the provided inputs and computes the final
    result.
    
    :param inputs: List of integers to execute as an Intcode program.
    :type inputs: list(int)
    :param restore_gravity_assist: Whether or not to restore the gravity assist
        by modifying the input program.
    :type restore_gravity_assist: bool
    :return: Final output of the program.
    :rtype: int
    '''
    # restore gravity assist?
    if restore_gravity_assist:
        inputs[1] = 12
        inputs[2] = 2
    # create and execute program
    program = IntcodeProgram(inputs)
    program.run()
    # isolate final result
    return program.program[0]
Esempio n. 15
0
def start_on_black():
    input_queue = Queue()
    output_queue = Queue()

    program = IntcodeProgram(io_scheme=IntcodeProgram.IOScheme.QUEUE,
                             input_queue=input_queue,
                             output_queue=output_queue)

    program.initialize_memory_from_file('input.txt')

    input_queue.put(BLACK)

    painting_robot = Robot()
    painted_grid = defaultdict(int)

    while True:
        try:
            program.execute_next()
        except WaitingForInput:
            new_color = output_queue.get()
            direction = output_queue.get()

            painted_grid[painting_robot.get_grid_pos()] = new_color
            painting_robot.move(direction)

            input_queue.put(painted_grid[painting_robot.get_grid_pos()])
        except ProgramHalted:
            print('Program Complete')
            print(f'Painted {len(painted_grid.keys())} tiles at least once')
            break
Esempio n. 16
0
def paint(starting_panel_color):
    ip = IntcodeProgram(d9_input)
    dir_index = 0
    robot_pos = (0, 0)
    panels = defaultdict(int)
    panels[robot_pos] = starting_panel_color
    while 1:
        color, next_dir, halted = cycle(ip, panels[robot_pos])
        if halted:
            break
        panels[robot_pos] = color
        dir_index += 1 if next_dir else -1
        robot_pos = dirs_move[dirs[dir_index % 4]](robot_pos)
    return panels
Esempio n. 17
0
 def __init__(self, master, memory, **kwargs):
     self.master = master
     self.scale = 5
     self.padding = 50
     self.memory = memory
     self.memory[0] = 2
     self.program = IntcodeProgram(self.memory)
     self.program.run_till_input()
     self.state_history = []
     op = OutputParser(self.program.output)
     self.canvas = tk.Canvas(
         self.master,
         width=self.coord(op.width)+self.padding,
         height=self.coord(op.height)+self.padding
     )
     self.tile_mapping = {(x, y): Tile(
         self.canvas,
         self.scale,
         (x, y),
         (self.coord(x), self.coord(y)),
         ttype
     ) for x, y, ttype in op.tiles}
     self.score = 0
     self.score_label = self.canvas.create_text((50, 20), text='Score: 0')
     self.state_label = self.canvas.create_text(
         (250, 20), text='State: IDLE')
     self.canvas.pack()
     self.move_history = []
     self.moved = False
     self.canvas.bind("<Right>", lambda ev: self.set_next_dir(1))
     self.canvas.bind("<Left>", lambda ev: self.set_next_dir(-1))
     self.canvas.bind("<Up>", lambda ev: self.set_next_dir(0))
     self.canvas.bind("<Down>", lambda ev: self.step_back())
     self.canvas.bind("<1>", lambda event: self.canvas.focus_set())
     self.canvas.focus_set()
     self.master.after(0, self.refresh)
Esempio n. 18
0
def d7p2():
    highest_signal = 0
    for settings in permutations(range(5, 10)):
        curr_signal = 0
        ip_mapping = list(
            map(lambda curr_setting: IntcodeProgram(d7_input, curr_setting),
                settings))
        while all(not ip.halted for ip in ip_mapping):
            for ip in ip_mapping:
                ip.set_input(curr_signal)
                ip.run_till_output()
                if not ip.halted:
                    curr_signal = int(''.join(ip.output))
                ip.reset_output()
        highest_signal = max(highest_signal, curr_signal)
    return highest_signal
Esempio n. 19
0
def process_inputs_feedback(inputs):
    '''Executes the Intcode program on the provided inputs and computes the final
    result. Here, we use the [5, 9] phase settings range and a feedback loop to
    pass through the amplifiers multiple times.
    
    :param inputs: List of integers to execute as an Intcode program.
    :type inputs: list(int)
    :return: Maximum input to the thrusters.
    :rtype: int
    '''
    # prepare all possible permutations for phase settings:
    # we have X possibilities for the first one, X-1 for the second one,
    # X-2 for the third one... (no replacement)
    n_amplifiers = 5
    candidate_phase_settings = itertools.permutations(range(5, 10), n_amplifiers)
    thrusts = []
    
    IntcodeProgram.INSTANCE_ID = 0 # reset global instances IDs
    amplifiers = [ IntcodeProgram(inputs) for _ in range(n_amplifiers) ]    
    for phase_settings in candidate_phase_settings:
        # reset all amplifiers
        for amp in amplifiers:
            amp.reset()
        # prepare input for first amplifier
        amplifiers[0].push_memory(0)
        current_amplifier = 0
        running = True
        while running:
            # if necessary, initialize amplifier
            phase = phase_settings[current_amplifier]
            amplifiers[current_amplifier].check_running(phase)
            # run amplifier (either from scratch or from where it last
            # stopped)
            next_amp = amplifiers[current_amplifier].run_multiple(amplifiers)
            # . if we errored somewhere
            if next_amp is None:
                return None
            # . else if amplifiers loop has halted
            elif next_amp == -1:
                running = False
            # . else reassign the current amplifier index for next iteration
            else:
                current_amplifier = next_amp
        # remember the power sent to the thrusters with these settings
        output = amplifiers[current_amplifier].output[-1]
        thrusts.append(output)
    return max(thrusts)
Esempio n. 20
0
def d7p1():
    highest_signal = 0
    for settings in permutations(range(5), 5):
        curr_signal = 0
        for curr_setting in settings:
            ip = IntcodeProgram(d7_input, curr_setting)
            ip.set_input(curr_signal)
            ip.run()
            curr_signal = int(''.join(ip.output))
        highest_signal = max(highest_signal, curr_signal)
    return highest_signal
Esempio n. 21
0
def process_inputs(inputs, input):
    '''Executes the Intcode program on the provided inputs and computes the final
    result.
    
    :param inputs: List of integers to execute as an Intcode program.
    :type inputs: list(int)
    :param input: Specific input for the program execution.
    :type input: int
    :return: Final output of the program.
    :rtype: int
    '''
    # create program
    program = IntcodeProgram(inputs)
    # insert input in memory
    program.push_memory(input)
    # execute program
    program.run()
    # return last output
    return program.output[-1]
Esempio n. 22
0
def start_on_white():
    input_queue = Queue()
    output_queue = Queue()

    program = IntcodeProgram(io_scheme=IntcodeProgram.IOScheme.QUEUE,
                             input_queue=input_queue,
                             output_queue=output_queue)

    program.initialize_memory_from_file('input.txt')

    input_queue.put(WHITE)

    painting_robot = Robot()
    painted_grid = defaultdict(int)

    while True:
        try:
            program.execute_next()
        except WaitingForInput:
            new_color = output_queue.get()
            direction = output_queue.get()

            painted_grid[painting_robot.get_grid_pos()] = new_color
            painting_robot.move(direction)

            input_queue.put(painted_grid[painting_robot.get_grid_pos()])
        except ProgramHalted:
            break

    grid = [key for key in painted_grid.keys()]
    max_x = max(grid, key=lambda val: val[0])[0]
    max_y = max(grid, key=lambda val: val[1])[1]
    min_x = min(grid, key=lambda val: val[0])[0]
    min_y = min(grid, key=lambda val: val[1])[1]

    for y in range(max_y, min_y - 1, -1):
        for x in range(min_x, max_x + 1):
            print(' ' if painted_grid[(x, y)] == BLACK else '█', end='')
        print()
Esempio n. 23
0
def process_inputs(inputs, input=None, debug=False):
    '''Executes the Intcode program on the provided inputs and computes the final
    result.
    
    :param inputs: List of integers to execute as an Intcode program.
    :type inputs: list(int)
    :param input: Integer to provide as input to the program.
    :type input: int
    :param debug: Whether or not the IntcodeProgram should debug its
        execution at each instruction processing.
    :type debug: bool
    :return: Last output of the program.
    :rtype: int
    '''
    # create program
    program = IntcodeProgram(inputs, debug=debug)
    # insert input in memory if need be
    if input is not None:
        program.push_memory(input)
    # run program
    program.run()
    # get final result
    return program.output[-1]
Esempio n. 24
0
def compute_score(board, inputs, export=False, debug=False):
    '''Executes the Intcode program on the provided inputs and finds out the
    score of the player when the last block has been destroyed.
    
    :param board: Initial board.
    :type board: dict
    :param inputs: List of integers to execute as an Intcode program.
    :type inputs: list(int)
    :param export: Whether or not to export the board as an image at each game
        move.
    :type export: bool
    :param debug: Whether or not the IntcodeProgram should debug its
        execution at each instruction processing.
    :type debug: bool
    :return: Final score of the player.
    :rtype: int
    '''
    # get paddle and ball coordinates
    for (x, y), marker in board.items():
        if marker == 'H':
            px = x
        elif marker == 'O':
            bx = x
    init_n_blocks = None
    last_n_blocks = None
    # prepare the program instance to read the given inputs as an Intcode
    # program
    program = IntcodeProgram(inputs, debug=debug)
    # insert quarters to run in "free mode"
    program.program[0] = 2

    running = True
    score = None
    time = 0
    print('Remaining block(s):')
    # execute the program until it halts (but pause every 3 outputs)
    while running:
        # move the paddle to catch the ball and continue the game
        if px < bx:  # move right
            program.insert_memory(1)
        elif px > bx:  # move left
            program.insert_memory(-1)
        else:  # reset movement to null
            program.insert_memory(0)

        # execute until 3 digits have been outputted
        state = program.run(pause_every=3)
        # check for state:
        # . if paused: parse outputs and apply the actions
        if state == 'pause':
            x, y, id = program.output
            program.reset_output()
            if x == -1 and y == 0:
                score = id
                # if outputting score and no more blocks: game ends
                if n_blocks == 0:
                    # (export board?)
                    if export:
                        export_board(time, board)
                    running = False
                    print('\n')
                    break
            else:
                if id == 0:
                    marker = None
                elif id == 1:
                    marker = 'W'
                elif id == 2:
                    marker = 'B'
                elif id == 3:
                    marker = 'H'
                    px = x
                else:
                    marker = 'O'
                    bx = x
                board[(x, y)] = marker
        # . else: stop the program
        elif state is None:
            running = False
            break

        # . check to see if all blocks have disappeared
        n_blocks = sum([1 if m == 'B' else 0 for m in board.values()])
        # (initial blocks count and initial export, if need be)
        if init_n_blocks is None:
            init_n_blocks = n_blocks
            if export:
                export_board(0, board)
                time += 1
        # (if number of remaining blocks changed, output it)
        if last_n_blocks != n_blocks:
            c = 50 * n_blocks // init_n_blocks
            suffix = ('{:%dd}' % (len(str(init_n_blocks)))).format(n_blocks)
            bar = '■' * c + ' ' * (50 - c)
            print('{} {} / {}'.format(bar, suffix, init_n_blocks), end='\r')
            last_n_blocks = n_blocks
        # (export board?)
        if export and n_blocks != init_n_blocks:
            if time % 2 == 0:
                export_board(time // 2, board)
            time += 1

    return score
Esempio n. 25
0
def d5p1():
    ip = IntcodeProgram(d5_input, 1)
    ip.run()
    return int(''.join(ip.output))
Esempio n. 26
0
def main():
    input_queue = Queue()
    output_queue = Queue()
    program = IntcodeProgram(io_scheme=IntcodeProgram.IOScheme.QUEUE,
                             input_queue=input_queue,
                             output_queue=output_queue)
    program.initialize_memory_from_file('input.txt')
    memory_dump = program.dump_memory()
    program.run_to_end()

    scaffolding = build_scaffolding(program)

    alignment_parameters = []

    for scaffold in scaffolding:
        if scaffolding.issuperset(scaffold.get_neighbors()):
            alignment_parameters.append(scaffold.x * scaffold.y)

    print(f'Part One: {sum(alignment_parameters)}')

    program.load_memory(memory_dump)
    program.set_memory_address(0, 2)

    drive_around(program)
Esempio n. 27
0
class App(object):
    def __init__(self, master, memory, **kwargs):
        self.master = master
        self.scale = 5
        self.padding = 50
        self.memory = memory
        self.memory[0] = 2
        self.program = IntcodeProgram(self.memory)
        self.program.run_till_input()
        self.state_history = []
        op = OutputParser(self.program.output)
        self.canvas = tk.Canvas(
            self.master,
            width=self.coord(op.width)+self.padding,
            height=self.coord(op.height)+self.padding
        )
        self.tile_mapping = {(x, y): Tile(
            self.canvas,
            self.scale,
            (x, y),
            (self.coord(x), self.coord(y)),
            ttype
        ) for x, y, ttype in op.tiles}
        self.score = 0
        self.score_label = self.canvas.create_text((50, 20), text='Score: 0')
        self.state_label = self.canvas.create_text(
            (250, 20), text='State: IDLE')
        self.canvas.pack()
        self.move_history = []
        self.moved = False
        self.canvas.bind("<Right>", lambda ev: self.set_next_dir(1))
        self.canvas.bind("<Left>", lambda ev: self.set_next_dir(-1))
        self.canvas.bind("<Up>", lambda ev: self.set_next_dir(0))
        self.canvas.bind("<Down>", lambda ev: self.step_back())
        self.canvas.bind("<1>", lambda event: self.canvas.focus_set())
        self.canvas.focus_set()
        self.master.after(0, self.refresh)

    def step_back(self):
        print('STEP BACK!')
        if len(self.state_history) > 0:
            self.program = loads(self.state_history.pop())
            self.move_history.pop()
            self.render_output()
        print(self.move_history)

    @property
    def ball(self):
        ball, = [t for t in self.tile_mapping.values() if t.ttype == 4]
        return (ball.x, ball.y)

    @property
    def paddle(self):
        paddle, = [t for t in self.tile_mapping.values() if t.ttype == 3]
        return (paddle.x, paddle.y)

    def set_next_dir(self, next_dir):
        print('NEXT DIR!', next_dir)
        self.move_history.append(next_dir)
        self.moved = False
        self.canvas.itemconfigure(self.state_label, text='State: MOVING')
        print(self.move_history)

    def coord(self, x):
        return x*self.scale+self.padding

    def refresh(self):
        if self.moved:
            self.master.after(5, self.refresh)
            return
        if len(self.state_history) == 100:
            self.state_history.pop(0)
        self.state_history.append(dumps(self.program))
        self.program.set_input(self.move_history[-1])
        self.program.next()
        self.program.run_till_input()
        self.moved = True
        self.canvas.itemconfigure(self.state_label, text='State: IDLE')
        self.render_output()
        if self.check_state():
            self.master.after(5, self.refresh)

    def render_output(self):
        op = OutputParser(self.program.output)
        for x, y, ttype in op.tiles:
            self.tile_mapping[(x, y)].update(ttype)
        if op.score is not None:
            self.canvas.itemconfigure(
                self.score_label, text='Score: %s' % op.score)

    def check_state(self):
        # if self.ball[1] >= self.paddle[1]:
        #     return False
        if len([t for t in self.tile_mapping.values() if t.ttype == 2]) == 0:
            return False
        return True
Esempio n. 28
0
def main(stdscr):
    automatic = True

    # Clear screen
    stdscr.clear()

    input_queue = Queue()
    output_queue = Queue()

    program = IntcodeProgram(io_scheme=IntcodeProgram.IOScheme.QUEUE,
                             input_queue=input_queue,
                             output_queue=output_queue)
    program.initialize_memory_from_file('input.txt')
    program.set_memory_address(0, 2)

    tiles = {}

    while True:
        try:
            program.execute_next()

        except WaitingForInput:
            process_frame(program, tiles)

            draw_screen(stdscr, tiles)

            if automatic:
                sleep(.05)
                paddle = get_paddle_x(tiles)
                ball = get_ball_x(tiles)

                if paddle > ball:
                    program.queue_input(-1)
                elif paddle < ball:
                    program.queue_input(1)
                else:
                    program.queue_input(0)

            else:
                capture_key = stdscr.getch()

                if capture_key == curses.KEY_LEFT:
                    program.queue_input(-1)
                elif capture_key == curses.KEY_RIGHT:
                    program.queue_input(1)
                else:
                    program.queue_input(0)

        except ProgramHalted:
            process_frame(program, tiles)
            break

    draw_screen(stdscr, tiles)

    stdscr.getch()
Esempio n. 29
0
def save_robots(simple_map, inputs, export=False, debug=False):
    '''Saves the robots by walking on the scaffolds, and also collects dust.
    
    :param simple_map: Map to walk.
    :type simple_map: dict(tuple(int, int), int)
    :param inputs: List of integers to execute as an Intcode program.
    :type inputs: list(int)
    :param export: Whether or not to ask for a continuous video feed and to
        export the resulting images.
    :type export: bool
    :param debug: Whether or not the IntcodeProgram should debug its
        execution at each instruction processing.
    :type debug: bool
    :return: Amount of dust collected during the process.
    :rtype: int
    '''
    # prepare the program instance to read the given inputs as an Intcode
    # program
    program = IntcodeProgram(inputs, debug=debug)
    # force the robot to wake up
    program.program[0] = 2

    # get full path
    (x, y), dir = [(k, v) for k, v in simple_map.items() if v != 1][0]
    visited = set([(x, y)])
    path = []
    steps = 0
    while len(visited) != len(simple_map):
        # get all possible directions from current state (the robot cannot make
        # a U-turn!)
        possible_dirs = DIRECTION_POSSIBILITES[dir]
        # get relevant neighbors
        neighbors = {}
        for move_dir in range(2, 6):
            # robot cannot make a U-turn!
            if move_dir not in possible_dirs:
                continue
            dx, dy = DIRECTION_DELTAS[move_dir]
            nx, ny = x + dx, y + dy
            if (nx, ny) in simple_map:
                val = 1 if (nx, ny) in visited else 0
                if move_dir == dir:
                    val -= 1
                neighbors[(nx, ny)] = (val, move_dir)
        # get best neighbor: if possible, not already visited
        neighbor, (_, d) = sorted(neighbors.items(), key=lambda k: k[1][0])[0]
        x, y = neighbor
        if d != dir:
            if steps > 0:
                steps += 1
                path.append(str(steps))
            steps = 0
            if possible_dirs.index(d) > possible_dirs.index(dir):
                path.append('R')
                dir = dir + 1 if dir < 5 else 2
            else:
                path.append('L')
                dir = dir - 1 if dir > 2 else 5
        else:
            steps += 1
        visited.add((x, y))

    if path[-1] == 'L' or path[-1] == 'R':
        path = path[:-1]
    path_str = ','.join(path)
    print(path_str)

    # movements = { 'A': [], 'B': [], 'C': [] }
    # movement = ''
    # c = 0
    # for m in [ 'A', 'B', 'C' ]:
    #     while movement in path_str[len(movement):]:
    #         movement += path_str[c]
    #         c += 1
    #     movements[m] = movement
    # print(movements)
    # # A L,11,R,3,R,3,L,5,
    # # B L,11,R,3,R,3,R,11,
    # # A L,11,R,3,R,3,L,5,
    # # C L,9,L,5,R,3,
    # # A L,11,R,3,R,3,L,5,
    # # B L,11,R,3,R,3,R,11,
    # # C L,9,L,5,R,3,
    # # B L,11,R,3,R,3,R,11,
    # # C L,9,L,5,R,3,
    # # A/B L,11,R,3,R,3
    #
    # movements_chain = []
    # for move, pattern in movements.items():
    #     if path_str.startswith(pattern):
    #         movements_chain.append(move)
    #         path_str = path_str[len(move)-1:]
    #         print(path_str)
    # print(movements_chain)
    # return

    # separate paths into subpatterns (done by hand)
    A = encode_movement('L,12,R,4,R,4,L,6')
    B = encode_movement('L,12,R,4,R,4,R,12')
    C = encode_movement('L,10,L,6,R,4')
    movements = encode_movement('A,B,A,C,A,B,C,B,C,A')

    # prepare movements
    program.push_memory(movements)
    program.push_memory(A)
    program.push_memory(B)
    program.push_memory(C)
    program.push_memory([ord('y' if export else 'n'), 10])

    # run the program to move the robot
    program.run()
    print('Finished computing.')
    # export maps if need be
    if export:
        full_map = ''.join([chr(x) for x in program.output])
        all_maps = [
            m for m in full_map.split('\n\n') if len(m) > 0 and m[0] == '.'
        ]
        if not os.path.exists(EXPORT_DIR):
            os.makedirs(EXPORT_DIR)
        for i, map in enumerate(all_maps):
            export_map(i, map)

    return program.output[-1]
Esempio n. 30
0
 def get_point(self, x, y):
     ip = IntcodeProgram(self.memory)
     ip.set_input(x)
     ip.set_input(y)
     ip.run()
     return int(ip.output[0])