def dfs(stack, seen):
    visit_count = 0
    max_depth = -1
    while stack:
        top = stack.get()
        visit_count += 1
        if is_solution(top['state']):
            print('Found solution {} of {} moves in {} visits'.format(
                top['moves'], len(top['moves']), visit_count))
            break
        for direction in ('U', 'L', 'D', 'R'):
            moves_so_far = top['moves']
            if len(moves_so_far) > max_depth:
                max_depth = len(moves_so_far)
            current_state = top['state']
            if can_move_blank(direction, current_state):
                new_state = new_after_move(direction, current_state)
                if new_state not in seen:
                    seen.add(new_state)
                    new_moves = moves_so_far + direction
                    stack.put({'state': new_state, 'moves': new_moves})

    stack_size = py_mem_prof.total_size(stack)
    seen_size = py_mem_prof.total_size(seen)

    if resource:
        resource_usage = resource.getrusage(resource.RUSAGE_SELF)
        ru_maxrss = resource_usage.ru_maxrss
    else:
        resource_usage = None
        ru_maxrss = None

    return max_depth, stack_size, seen_size, ru_maxrss
def bfs(queue, seen):
    visit_count = 0
    while queue:
        head = queue.get()
        visit_count += 1
        if is_solution(head['state']):
            print('Found solution {} of {} moves in {} visits'.format(
                head['moves'], len(head['moves']), visit_count))
            break
        for direction in ('U', 'L', 'D', 'R'):
            moves_so_far = head['moves']
            current_state = head['state']
            if can_move_blank(direction, current_state):
                new_state = new_after_move(direction, current_state)
                if new_state not in seen:
                    seen.add(new_state)
                    new_moves = moves_so_far + direction
                    queue.put({'state': new_state, 'moves': new_moves})
def a_star(priority_queue, seen):
    visit_count = 0
    while priority_queue:
        t = priority_queue.get()
        lowest = {'state': t[1], 'moves': t[2]}
        visit_count += 1
        if is_solution(lowest['state']):
            print('Found solution {} of {} moves in {} visits'.format(
                lowest['moves'], len(lowest['moves']), visit_count))
            break
        for direction in ('U', 'L', 'D', 'R'):
            moves_so_far = lowest['moves']
            current_state = lowest['state']
            if can_move_blank(direction, current_state):
                new_state = new_after_move(direction, current_state)
                if new_state not in seen:
                    seen.add(new_state)
                    new_moves = moves_so_far + direction
                    total = len(moves_so_far) + heuristic(new_state)
                    priority_queue.put((total, new_state, new_moves))
            new_nested_list[blank_row + 1][blank_col] = '0'
            new_nested_list[blank_row][blank_col] = temp
            return new_nested_list
    elif direction == 'L':
        if blank_col == 0:
            1 / 0
        else:
            temp = new_nested_list[blank_row][blank_col - 1]
            new_nested_list[blank_row][blank_col - 1] = '0'
            new_nested_list[blank_row][blank_col] = temp
            return new_nested_list
    else:
        1 / 0


assert to_str(new_after_move('U', to_2d_list('123405678'))) == '103425678'
assert to_str(new_after_move('L', to_2d_list('123405678'))) == '123045678'
assert to_str(new_after_move('D', to_2d_list('123405678'))) == '123475608'
assert to_str(new_after_move('R', to_2d_list('123405678'))) == '123450678'


def heuristic(state):
    total = 0
    for char in state:
        current_pos = state.index(char)
        current_coord = (current_pos // 3, current_pos % 3)
        if char == '0':
            right_position = (0, 0)
        elif char == '1':
            right_position = (0, 1)
        elif char == '2':