Розберемо задачу 8358 з e-olymp. Джерело задачі — 2018 Azerbaijan School Competition, II Stage, April 8, Problem K. На e-olimp на дату написання статті задача опублікована лише російською, тому перекладаю сам:
Середнє значення – 1
(https://www.e-olymp.com/uk/problems/8358)
Проект "Середня вага школяра школи" вирішили виконати Мамед з Самедом. Що вони будуть робити з цим числом, вони не розкривають. Вони попросили зважитися всіх учнів школи і занесли результати в таблицю. Допоможіть їм підрахувати середню вагу учнів. Але вони просять, щоб учнів з найбільшою і з найменшим вагою не враховувати. Єдине їх упущення, вони не підрахували загальну кількість учнів, але це, звичайно, не завадить вам підрахувати то, що вони просять.
Вхідні дані
У кількох рядках задані ваги учнів в кілограмах, розділених пропусками (одним або кількома) або символом кінця рядка. Читати ваги учнів до кінця введення.
Вихідні дані
Середня вага учнів школи без урахування учнів з найбільшою і найменшою вагою. Відповідь виводити з точністю до кілограм.
Ліміт часу 1 секунда
Ліміт використання пам'яті 128 MB
Вхідні дані # 1
40 23 27
59 68 23 84 27
53 46
Вихідні дані # 1
46
В першу чергу треба врахувати, що через невідому кількість рядків вхідних даних, єдиним способом отримати вхідні дані – це використати введення з файлу. Будемо читати рядки з файлу до тих пір, поки не закінчиться файл. Пропоную кожний рядок вхідних даних записувати в тимчасовий список, а далі елементи цього тимчасового списку додавати до основного списку. Код цієї частини програми:
inputfile = open('input.txt', 'r')
outputfile = open('output.txt', 'w')
weights = []
for line in inputfile:
lst = [int(x) for x in line.split()]
weights.extend(lst)
Далі ми можемо використати list comprehension з умовою, наприклад, так ефектно:
weights = [x for x in weights if x != max(weights) and x != min(weights)]
В результаті в новому списку weights будуть лише потрібні дані, всі максимальні і мінімальні ваги в новий список weights не попадуть. Але так робити не треба, тому що це неоптимально по часу і непрофесійно на співбесіді на роботу. Річ в тому, що при кожній ітерації циклу, проходить порівняння значення елементу списку з максимальним і мінімальним елементом списку. І кожного разу python буде обраховувати максимальне і мінімальне значення. Так як список у нас протягом обробки циклом не змінюється, то буде правильним визничити максимальне і мінімальне значення списку до циклічного перебору:
max_weights = max(weights)
min_weights = min(weights)
weights = [x for x in weights if x != max_weights and x != min_weights]
Зверніть увагу на інформативність змінних. В олімпіадному програмуванні часто поспішають і так змінні не називають, а дарма. Рекомендую назви змінним давати розумно, у професійному програмуванню так і роблять.
Ну і на останок, в умові задачі є округлення, це в Python дуже дискутивна тема. Як мінімум, нагадаю, що Python версії 2 виконує так зване «арифметичне округлення», як Pascal, C++ і як на уроках математики, а Python версії 3 при використанні функції round() виконує так зване «банківське округлення» або «округлення до парного». В даній задачі тести обрані таким чином, що при здачі в Python версії 3 ніяких проблем немає, про округлення в Python 3 на «Плетиві» буде окрема стаття, а тим, хто про дива округлення чує вперше, банківське округлення в Python 3 (і не лише там) виглядає так:
>>> round(1.5)
2
>>> round(2.5)
2
>>> round(3.5)
4
>>> round(4.5)
4
>>> round(5.5)
6
>>> round(6.5)
6
>>> round(7.5)
8
>>> round(8.5)
8
І не забувайте прибиратися після себе. Принцип простий. Ви відкрили якийсь файли? Ви відкрили, вам і закривати.
Документація третього Python вимагає так:
If you’re not using the with keyword, then you should call f.close() to close the file and immediately free up any system resources used by it. If you don’t explicitly close a file, Python’s garbage collector will eventually destroy the object and close the open file for you, but the file may stay open for a while. Another risk is that different Python implementations will do this clean-up at different times.
Успіхів!