This page is hosted for free by zzz.com.ua, if you are owner of this page, you can remove this message and gain access to many additional features by upgrading your hosting to PRO or VIP for just 32.50 UAH.
Do you want to support owner of this site? Click here and donate to his account some amount, he will be able to use it to pay for any of our services, including removing this ad.

Введення даних з файлу і оптимальне використання list comprehension

Друк

Розберемо задачу 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.

Успіхів!