Example #1
0
def main(display=False):
    program = Intcode()
    program.load_from_file('inputs/day_13_input.txt')
    program.memory[0] = 2  # Hack to play for free
    x_ball = None
    x_paddle = None
    score = 0
    joystick = 0
    monitor = Display(screendict)
    while not program.ishalted:
        while not program.iswaiting and not program.ishalted:
            program.step()
        while program.output_buffer:
            x = program.output()
            y = program.output()
            v = program.output()
            if x == -1 and y == 0:
                score = v
            else:
                if v == 3:
                    x_paddle = x
                if v == 4:
                    x_ball = x
                monitor.update({(x, y): v})
        if (x_ball is not None) and (x_paddle is not None):
            joystick = (x_ball > x_paddle) - (x_ball < x_paddle)
            program.input(joystick)
            program.step()  # Clear the waiting condition
        if display:
            monitor.show(legend='SCORE: {0}'.format(score))
    print("\nFinal score: {0}\n".format(score))
    return score
Example #2
0
def paint_hull(hull, coordinates):
    # Circular list with main directions in a cartesian frame (CW order)
    # Default (starting) direction is the first, to the North
    directions = deque([(0, 1), (1, 0), (0, -1), (-1, 0)])

    def turn_left():
        directions.rotate(1)

    def turn_right():
        directions.rotate(-1)

    def direction():
        return directions[0]

    program = Intcode()
    program.load_from_file('inputs/day_11_input.txt')
    while True:
        # Provide panel color as input
        try:
            program.input(hull[coordinates])
        except KeyError:
            program.input(0)  # All panels start black
        # Let's wait for the two outputs
        while (len(program.output_buffer) < 2) and not program.ishalted:
            program.step()
        if program.ishalted:
            break
        # First output is the colour
        colour = program.output()
        hull[coordinates] = colour
        # Second output is the rotation
        rotation = program.output()
        if rotation == 0:
            turn_left()
        elif rotation == 1:
            turn_right()
        else:
            raise ValueError()
        coordinates = advance(coordinates, direction())
    return hull, coordinates
Example #3
0
def main(display=False):
    """
    We'll only use LEFT rotations, since R = LLL, so we'll recover it later.

    We'll also work with the map spread out on a single line
    In this configuration, L-R is -/+ 1 and U-D is -/+ N, (N is a line length)

    First we trace the scaffold with the strategy "keep going forward until you
    can only turn, then turn - all until you can only backtrack".
    Then we try to compress the obtained command sequence, and give the result
    to the Intcode computer to process.
    """
    # Prepare the map
    lines = map_scaffolding()
    N = len(lines[0])
    mapstr = ''.join(lines)

    # Circular list with main directions in CW order (Up Right Down Left)
    directions = deque([-N, +1, +N, -1])

    def turn_left():
        directions.rotate(+1)  # This "rotates the robot"

    def front():
        return directions[0]  # This indicates "the direction the robot faces"

    def next_tile(position, last_visited):
        """
        Returns true if the tile in front of the robot is a valid scaffold tile
        We make sure that it's not a recently visited scaffold, so we're not
        just backtracking, hence the "valid"
        """
        try:
            new_position = position + front()
            if mapstr[new_position] == '#' and new_position != last_visited:
                # Also check that we're not crossing the L or R borders
                if not (((position % N) == 0 and front() == -1) or
                        ((position % N) == N - 1 and front() == +1)):
                    return True
        except IndexError:
            pass
        return False

    # PATHFINDING & COMMAND BUILDING
    # Find the robot
    robot_pos = re.search(r'[^\.\#]', mapstr).start()
    last_visited = None
    robot_dir = {'^': -N, '>': +1, 'v': +N, '<': -1}[mapstr[robot_pos]]
    # Align reference system, since front() by default is pointing Up
    while front() != robot_dir:
        turn_left()
    # Build command sequence as a list
    commands = []
    while True:
        rotation_timeout = 0
        while not next_tile(robot_pos, last_visited) and rotation_timeout < 4:
            turn_left()
            commands.append('L')
            rotation_timeout = rotation_timeout + 1
        if rotation_timeout == 4:
            break  # We're spinning in circles, nowhere left to go...
        counter = 0
        while next_tile(robot_pos, last_visited):
            last_visited = robot_pos
            robot_pos = robot_pos + front()
            counter = counter + 1
        commands.append(str(counter))
    # Cut away last Ls while spinning in cicles and convert LLL into R
    while commands[-1] == 'L':
        commands.pop(-1)
    replace_sublist(commands, ['L', 'L', 'L'], ['R'])
    # Compress commands
    symbols = ['A', 'B', 'C']
    sequence, functions = compress(commands, symbols, maxlen=20)

    # RUNNING THE INTCODE PROGRAM
    program = Intcode()
    program.load_from_file('inputs/day_17_input.txt')
    program.memory[0] = 2  # Manual override
    video_feed = {True: 'y', False: 'n'}[display]
    # Build program input
    program_input = '{0}\n'.format(sequence)
    for s in symbols:
        program_input = program_input + '{0}\n'.format(functions[s])
    program_input = program_input + '{0}\n'.format(video_feed)
    for x in program_input:
        program.input(ord(x))
    # Run the program
    if display:
        # Live video feed
        screen_buffer = ''
        while not program.ishalted:
            program.step()
            if program.output_buffer:
                screen_buffer += chr(program.output())
                # TODO: handle values outside of chr range
            if screen_buffer[-2:] == '\n\n':
                Display.clear()
                print(screen_buffer, end='')
                screen_buffer = ''
        dust = ord(screen_buffer[-1])  # Reconstruct dust from last output
    else:
        # Output only
        program.execute()
        dust = program.output_buffer[-1]
    # Output
    print("\nFound a solution with sequence: {0}".format(sequence))
    for symbol in symbols:
        print("{0}: {1}".format(symbol, functions[symbol]))
    print("\nTotal dust collected: {0}\n".format(dust))
    return dust