Example #1
0
def play(program, fps=0):
    # type: (NewProgram, int) -> int
    '''
    Play the game until it ends
    '''
    program[0] = 2
    pointer = 0
    relative_base = 0
    input = []
    game_map = None
    while pointer != -1:
        program, output, pointer, relative_base = run_program(
            program, input, pointer, True, relative_base)
        game_map = update_game_map(output, game_map)
        if fps:
            print_game_map(game_map)
            sleep(1 / fps)
        paddle_pos = find_object(game_map, 3)
        ball_pos = find_object(game_map, 4)
        if (ball_pos is None or paddle_pos is None):
            input = [0]
            continue
        input = [(ball_pos.x > paddle_pos.x) - (ball_pos.x < paddle_pos.x)]
    if fps:
        print_game_map(update_game_map(output, game_map))
    return game_map[Point(-1, 0)]
Example #2
0
def paint(program, start_color):
    # type: (NewProgram, int) -> Tuple[int, PaintedArea]
    '''
    Run a painting program on the robot
    '''
    directions = [Direction(0, -1), Direction(1, 0), Direction(0, 1), Direction(-1, 0)]
    painted_area = defaultdict(lambda: defaultdict(lambda: -1))
    painted_area[0][0] = start_color
    position = Point(0, 0)
    direction = 0
    pointer = 0
    relative_base = 0
    while pointer != -1:
        current_color = max(painted_area[position.y][position.x], 0)
        program, output, pointer, relative_base = run_program(program, [current_color], pointer, True, relative_base)
        painted_area[position.y][position.x] = output[0]
        if output[1] == 1:
            direction = (direction + 1) % len(directions)
        else:
            direction = (direction - 1) % len(directions)

        position.x = position.x + directions[direction].x
        position.y = position.y + directions[direction].y

    nb_painted = 0
    for y in painted_area:
        for x in painted_area[y]:
            if painted_area[y][x] > -1:
                nb_painted += 1

    return nb_painted, painted_area
Example #3
0
def count_tiles(program, tile_type):
    # type: (NewProgram, int) -> int
    '''
    Count the number of tiles of a given type.
    '''
    _, output, _, _ = run_program(program)
    count = 0
    for i in range(0, len(output) // 3):
        if output[3 * i + 2] == tile_type:
            count += 1

    return count
Example #4
0
def run(with_tests = True):
    with open(os.path.dirname(__file__) + os.sep + 'input.txt', 'r') as in_file:
        program = ast.literal_eval('[' + in_file.read().strip() + ']')

    checks_d17p1()

    _, output, _, _ = run_program(program)
    system_map, vacuum_state = build_map(output)
    d17p1 = sum_alignement_parameters(find_intersections(system_map))
    print(f'Day 17, Part 1 : {d17p1}') # 8928

    checks_d17p2()

    instructions = generate_instructions(system_map, vacuum_state)
    d17p2 = move_robot(program, instructions)
    print(f'Day 17, Part 2 : {d17p2}') # 880360
Example #5
0
def build_map(program):
    # type: (Program) -> Tuple[SectionMap, SectionMap, Point]
    '''
    Builds the section map by keeping the wall to the right
    '''
    section_map = defaultdict(lambda: -2, {Point(0, 0): 3})
    distance_map = defaultdict(lambda: sys.maxsize, {Point(0, 0): 0})

    pointer = 0
    relative_base = 0
    direction = 1
    position = Point(0, 0)
    oxygen_system_location = None

    while pointer != -1:
        program, output, pointer, relative_base = run_program(
            program, [direction + 1], pointer, True, relative_base)
        result = output[0]
        if result == 0:
            section_map[position + directions[direction]] = -1
            # Droid hit a wall, change the direction to keep the wall on the right
            direction = next_direction[direction]
        else:
            position += directions[direction]
            section_map[position] = max(section_map[position], result)
            distance_map[position] = min(
                [distance_map[position + directions[i]]
                 for i in range(0, 4)]) + 1
            if result == 2:
                oxygen_system_location = position
            # Droid didn't hit a wall, go back to the previous direction to keep the wall on the right
            direction = next_direction.index(direction)
        # Back to the start and all direction from the start are known, the map is completed
        if position == Point(0, 0) and section_map[directions[
                0]] != -2 and section_map[directions[1]] != -2 and section_map[
                    directions[2]] != -2 and section_map[directions[3]] != -2:
            break
    return section_map, distance_map, oxygen_system_location
Example #6
0
def move_robot(program, instructions):
    # type: (Program, Text) -> int
    '''
    Moves the robot and return the amount of collected dust
    '''
    main_routine, functions = compress_instructions(instructions)

    # Found by hand...
    main_routine = "A,B,A,B,A,C,B,C,A,C"
    functions = {'A': 'L,6,R,12,L,6', 'B': 'R,12,L,10,L,4,L,6', 'C':'L,10,L,10,L,4,L,6'}

    input = list(map(ord, main_routine))
    input.append(10)
    for function in functions.values():
        input.extend(map(ord, function))
        input.append(10)
    input.append(ord('n'))
    input.append(10)

    program[0] = 2
    _, output, _, _ = run_program(program, input)

    return output[-1]
Example #7
0
def get_status(x, y, program):
    _, output, _, _ = run_program(program, [x, y])
    return output[0] == 1