Python

Помогите с задачей по питону

В некотором файле содержатся детские имена. Каждое имя указано с новой строки. После имени через пробел записано одно целое число - количество названных этим именем детей. Имена в файле перемешаны в случайном порядке.
Напишите программу, которая считает данные из файла и выведет на экран 5 наиболее популярных имен (каждое в отдельной строке). Имя файла подается на вход и заранее не известно. Если указанного файла не существует, необходимо вывести сообщение "Файл не найден".
Пример:
Если в файле находятся следующие строки:
Аня 5
Саша 10
Кирилл 150
Игорь 1
Юля 999
Миша 2
Вы должны вывести имена Юля, Кирилл, Саша, Аня, Миша (в порядке убывания количества, каждое в отдельной строке)
Вот так можно:
 with open(input(), 'r') as f:
raw = ((int(freq), name) for line in f for name, freq in [line.split()])
top = sorted(raw, reverse = True)[:5]

print(*(name for _, name in top), sep = '\n')
Пример файла kids.txt:
 Аня 5
Саша 10
Кирилл 150
Игорь 1
Юля 999
Миша 2
Пример ввода:
 kids.txt 
Вывод:
 Юля
Кирилл
Саша
Аня
Миша

Читаем строки, бьём на поля, складываем в кортежи вида (5, 'Аня'). Поскольку популярность идёт первым полем, она и определяет порядок сортировки. Сортируем данные из файла по убыванию. Сложность получается O(n log n), где n - количество записей в файле.

Правда, в этой реализации есть недостаток: сортируется весь файл, когда нам достаточно лишь первых пяти строк по убыванию количества. Немного усложнив реализацию, получаем константные требования по памяти - хранится не более 5 элементов одновременно:
 from bisect import bisect_left
from functools import reduce

def add_lmt(lst, e):
p = bisect_left(lst, e)
return lst if p >= 5 else lst[:p] + [e] + lst[p:4]

with open(input(), 'r') as f:
top = reduce(add_lmt, ((-int(freq), name) for line in f for name, freq in [line.split()]), [])

print(*(name for _, name in top), sep = '\n')
bisect_left возвращает нам позицию для вставки в отсортированный список. Функция add_lmt добавляет элемент в список, если по порядку ему положено быть среди первых 5, и при этом убирает последний элемент, если он - пятый. Используя её, свёртываем весь файл в 5 топовых имён.
Популярность храним как отрицательную величину, т.к. bisect умеет нормально работать только с возрастающими списками.
Здесь сложность уже можно считать линейной, хотя и с константой log 5.
Сламбек Нурумов
Сламбек Нурумов
87 571
Лучший ответ
Каргаев Азиз выдает ошибку во время исполнения (RE)