2.6. Проект «Анализ качества образовательной программы»

Вы уже изучили все темы раздела и сейчас подходите к заключительному заданию. Эта задача похожа на те, что решают Python-разработчики на практике. Она поможет вам повторить пройденный материал и применить полученные знания.

Задача состоит из нескольких блоков:

  • Контекст. В реальной жизни задача не существует сама по себе, а возникает из определённого бизнес-контекста. Поэтому мы добавили небольшое описание трансформации задачи, от первого запроса до её финального вида.
  • Подсказки. Помощь в решении, если зайдёте в тупик. Комментарии к ключевым моментам решения задачи в формате FAQ.
  • Разбор. Подробный разбор задачи от автора, специалиста из Яндекса: от составления алгоритма решения до реализации и пояснения каждого блока кода.

Важно

Эта задача «со звёздочкой», она посложнее предыдущих. Если не справитесь — ничего страшного: в программировании редко что-то получается с первого раза. Сделайте паузу, перечитайте теорию и возвращайтесь с новыми силами и хорошим настроением.

Перед решением задачи

Повторите:

  • Ввод данных.
  • Условный оператор.
  • Вложенные циклы.
  • Вывод данных. Форматирование.

Изучите дополнительно:

  • Функция .map() и метод .split() для считывания данных.

И ещё один совет напоследок: рекомендуем работать с задачей последовательно.

  1. Изучите контекст.
  2. Ознакомьтесь с условием задачи.
  3. Попробуйте решить её самостоятельно.
  4. Если понадобится помощь — обратитесь к подсказкам. Если совсем тяжко — изучите разбор и попробуйте после самостоятельно решить.
  5. Когда решите задачу, сравните свой вариант с решением от специалиста.

Проект

Светлана Овсянникова

Светлана Овсянникова
Ex-разработчик в Яндекс Образовании

Привет! Я Света, разработчик в Яндекс Образовании. Ниже разберу, как мы смогли формализовать очень абстрактную задачу, с которой столкнулись на работе. А затем покажу её решение. Приглашаю вас пройти этот путь вместе со мной.

Контекст

Ежегодно компания проводит курс «Программирование на Python» для школьников и студентов средних учебных заведений.

Чтобы с каждым запуском образовательной программы ученики достигали более высоких результатов, анализируем опыт прохождения и делаем изменения часто даже по ходу программы. Таким образом нам нужно было собрать данные и провести анализ, чтобы сделать вывод, хорошо или плохо проходит курс и на что стоит обратить внимание.

В первом приближении задача выглядела следующим образом:

Условие задачи:
Нужно собрать и проанализировать данные с курса, чтобы на их основе понять, как идёт учебная программа.
Ввод:
Данные о курсе
Вывод:
Курс проходит хорошо или плохо

В текущем виде абсолютно непонятно: какие данные приходят на вход, как их нужно обрабатывать, из чего в целом формируется вывод. А значит, надо разбираться, запрашивать, как всё устроено и в каком виде ожидают результат.

Начинаем погружение!

Аналитика образовательной программы

В первую очередь я решила уточнить, что значит «курс проходит хорошо или плохо»? Пообщалась с руководителем. Оказывается, он имел в виду, что «хорошо или плохо» — это интерпретация статистики по успеваемости учеников на курсе. Если у участников программы получается набирать больше определённого процента всех возможных баллов (например, больше 50%), значит, всё «хорошо», иначе — «плохо».

При этом важно не забывать о разбросе данных об успеваемости, чтобы определять ситуации, когда небольшим количеством прилежных учеников достигается высокий средний рейтинг. Порекомендовал собрать ещё максимальный и минимальный рейтинг ученика на программе, а также посмотреть на рейтинги лучших. Так будет собираться более полная картинка о реальном состоянии дел.

Ещё он подробнее рассказал про саму программу, для которой мы решаем задачу:

  • У задачи глобальное применение. На данный момент обучение проводится очно в более чем в 20 городах России. То есть мы делаем дополнительный функционал, которым будут пользоваться одновременно 20+ образовательных программ.

  • Есть конкретная структура обучения, из которой формируется успеваемость/рейтинг учеников. Обучение состоит из четырёх активностей, каждая из которых вносит свой вклад в рейтинг:

    • Каждое занятие включает в себя теоретическую часть, где преподаватель объясняет новый материал.
    • И практическую часть, в ходе которой ученики пишут код и выполняют задания в определённой системе.
    • Для закрепления материала выдаются домашние задания.
    • Для проверки знаний проводятся контрольные работы.

Далее, получив больше подробностей о задаче и образовательной программе, я задумалась, а какие данные и в каком виде мы собираем? С этим запросом обратилась к команде, которая запускала курс.

Оказалось, что команда использовала аналитическую систему, которая уже собирала и хранила данные с программ. В том числе и необходимые нам для расчёта успеваемости.

Блок

Что хранится

Успеваемость

  • Оценки за активность на занятии

  • Оценки за самостоятельную работу

  • Оценки за домашние задания

  • Оценки за контрольные работы

  • Оценки за другие виды деятельности
    (на некоторых программах есть дополнительные активности)

  • Рейтинги

Посещаемость

  • Количество посещённых занятий

  • Количество пропущенных занятий

  • Причины пропусков

Вовлечённость

  • Количество ответов на занятиях

  • Участие в дискуссиях

  • Количество решений необязательных заданий

  • Вопросы, задаваемые преподавателю

  • Изучение дополнительных учебных материалов

Фидбэк

  • Оценки курса учениками

  • Комментарии к материалам курса

  • Отзывы о преподавателях

  • Сложные и лёгкие темы (по мнению учеников)

  • Предложения по улучшению программы

Меня предупредили, что очистка и обработка данных пока настраивается, поэтому данные по успеваемости могут содержать ошибки и стоит их лишний раз проверять. В результате я уточнила задачу, нашла готовые данные и поняла, как моя задача встраивается в глобальный контекст. Теперь можем составить рабочую формулировку!

Формулировка задачи

Давайте соединим все детали и соберём формулировку задачи.

Что нужно посчитать:

  • Рейтинг трёх лучших учеников.
  • Общие статистические параметры программы (минимальный, средний, максимальный рейтинг учеников).
  • Усвояемость программы. Если средний рейтинг будет больше 50% от максимального, сделаем вывод «Курс усваивается». Если меньше или равен 50% — «Курс не усваивается».

Ключевое:

  1. Ученик получает оценки для рейтинга за четыре вида активности по каждому занятию:
    • за активность на занятии (classwork_grade);
    • практику (selfwork_grade);
    • домашнюю работу (homework_grade);
    • и контрольные работы (testwork_grade).
  2. Рейтинг формируется из сумм оценок по каждому занятию по активностям, взятым с определённым весом (коэффициентом).
Рейтинг ученика = Сумма баллов по всем занятиям

Баллы за одно занятие = (
Оценка за активность x Коэффициент за активность
+ Оценка за практику x Коэффициент за практику
+ Оценка за домашнюю работу x Коэффициент за домашнюю работу
+ Оценка за контрольную работу x Коэффициент за контрольную работу
)
  1. Входные данные и итоговые расчёты нужно будет проверять на предмет возможных ошибок.
  2. Если ученика не было на занятии, или он не проявил себя, или не было этой активности, то оценка за активность будет равняться 0.

С учётом всех деталей задача преобразовалась в следующую:

Недавно начался очередной годовой курс «Программирование на Python». Прошла пара недель — и настало время подвести первые итоги: насколько курс усваивается учениками и нужно ли в нём что-то менять. Вас попросили собрать статистику по успеваемости учеников на курсе.

Для возможности принимать решения в рамках статистики необходимо:

  • Вывести общие показатели учеников программы: максимальное, среднее и минимальное значение рейтинга в процентах от максимально возможного.

  • Округлить результаты до целого значения по правилам математического округления: round().

  • Вывести лучших учеников: топ-3 лидера по рейтингу, их фамилии в порядке убывания рейтинга и заработанный процент от максимального количества баллов. Если у студентов равный рейтинг, они идут в порядке их ввода. Фамилии учеников уникальны.

  • На основе данных сделать предварительный вывод, насколько усваивается курс:

    • Если среднее значение рейтинга <= 50 — курс усваивается плохо.

    • Если среднее значение рейтинга > 50 — курс усваивается хорошо.

Также нужно проверить правильность введённых данных и расчётов.

Если есть ошибки, выводим «Во введённых данных ошибка».

Комментарии по вводу:

  • N (num_students) — число учеников в курсе.

  • M (num_lessons) — количество занятий в курсе.

  • Q (max_rating) — максимальный рейтинг.

  • cw (classwork_coefficient) — коэффициент для активности на занятии.

  • sw (selfwork_coefficient) — коэффициент для практики.

  • hw (homework_coefficient) — коэффициент для домашней работы.

  • tw (testwork_coefficient) — коэффициент для контрольной работы.

  • a (classwork_grade) — оценка за активность на занятии.

  • b (selfwork_grade) — оценка за практику на занятии.

  • c (homework_grade) — оценка за домашнюю работу на занятии.

  • d (testwork_grade) — оценка за контрольную работу на занятии.

Если не было активности, ученик отсутствовал либо не проявил себя на занятии — значение за активность будет 0.

Ограничения, которые следует учесть в работе программы:

  • N >= 3 (количество учеников больше или равно 3)

  • M > 0 (количество проведённых занятий 1 и больше)

  • cw, sw, hw, tw > 0 (все активности учитываются в рейтинге)

  • Рассчитанный максимальный рейтинг ученика на программе не должен превышать Q.

Ввод:

Вывод:

Строка с общими данными по программе
N M Q cw sw hw tw

Далее построчно вводятся оценки учеников в формате:
Фамилия
aᵢ,bᵢ,cᵢ,dᵢ

Max Average Min (максимальный, средний и минимальный рейтинг учеников программы)
Фамилия_1 Rating_1% (top-1)
Фамилия_2 Rating_2% (top-2)
Фамилия_3 Rating_3% (top-3)
Курс усваивается хорошо/плохо

4 5 190 1 2 4 6
Иванов
2,3,0,0
0,4,0,1
0,0,9,0
0,3,0,0
4,0,0,2
Петров
0,0,0,2
2,0,0,0
0,0,10,0
5,6,0,0
3,0,0,0
Сидоров
1,4,0,1
0,5,0,0
0,0,6,0
0,0,0,0
0,0,0,8
Сергеев
0,6,3,0
1,4,0,0
0,0,3,0
0,4,0,0
0,0,0,5

51 44 39
Сидоров 51%
Сергеев 44%
Иванов 42%
Курс усваивается плохо

Пояснение:

Все граничные условия выполнены. С данными всё в порядке.

Для Иванова рейтинг
6 ⋅ 1 + 10 ⋅ 2 + 9 ⋅ 4 + 3 ⋅ 6 = 80
округление 80 ∶ 190 = 42%

Для Петрова рейтинг
10 ⋅ 1 + 6 ⋅ 2 + 10 ⋅ 4 + 2 ⋅ 6 = 74
округление 74 ∶ 190 = 39%

У Сидорова = 51%
У Сергеева = 44%
Итого среднее (42 + 39 + 51 + 44) ∶ 4 = 44

2 5 210 3 4 7 8
Иванов
5,7,0,0
0,4,0,0
0,0,9,0
7,8,0,0
0,0,0,9
Петров
0,10,0,0
2,10,0,0
0,0,10,0
8,9,0,0
0,0,0,10

Во введённых данных ошибка

Пояснение:

Проверяем граничные условия. Количество учеников на курсе не больше или равно 3. Выводим ошибку.

Обратите внимание

Возможно, вы заметили, что ввод данных отличается от ввода данных в предыдущих задачах главы. Ранее вы считывали построчно — на каждой строчке были отдельные данные. А теперь несколько данных лежат в одной строчке, разделенные пробелом. и непонятно, как их считывать. Это нормально — так обычно бывает, когда начинаешь работать над новой для себя задачей и чего-то не знаешь. На практике программисты обычно либо советуются с более опытными коллегами, либо читают документацию, либо обращаются к GPT. Мы же дадим небольшую подсказку.

В данном случае для считывания данных из строчки мы будем использовать связку функции map() и метода .split().

Представим себе, что на вход подаются часы, минуты, секунды через пробел. Хотим эти данные считать в разные переменные.

14 30 45

Сделать можете это следующим образом.

# Ввод данных в одной строке 
hours, minutes, seconds = map(int, input().split()) 

# Вывод данных 
print("Часы:", hours) 
print("Минуты:", minutes) 
print("Секунды:", seconds)

В данном случае .split() разбивает строку на три части, игнорируя пробелы:

“14”, “30”, “45”

А map(int, …) превращает их в числа:

14, 30, 45

А дальше происходит присваивание переменных:

hours = 14
minutes = 30
seconds = 45

Теперь представим, что входные данные у нас идут с другим разделителем, запятой “,”:

14,30,45

В таком случае в методе .split() надо указать, какой разделитель у данных. Получится .split(“,”). Код изменится на следующий:

# Ввод данных в одной строке 
hours, minutes, seconds = map(int, input().split(“,”)) 

# Вывод данных 
print("Часы:", hours) 
print("Минуты:", minutes) 
print("Секунды:", seconds)

Пользуйтесь этой связкой для считывания данных в рамках задачи.

Теперь у вас есть всё необходимое для решения задачи. Удачи!

Если вы зашли в тупик, обратитесь к подсказкам. Мы собрали ответы на частые вопросы по этой задаче. Они наведут вас на мысль и помогут сдвинуться с мёртвой точки.

Подсказки

Не понимаю, с чего начать работу над задачей?

Попробуйте прочитать внимательно условие задачи и при прочтении каждой строчки выделять ключевую мысль — что именно нужно сделать? А затем подумайте над подходом/алгоритмом для решения задачи.

Алгоритм для решения задачи мог бы выглядеть следующим образом:

  1. Сначала считываем данные из первой строчки — общие данные.

  2. Затем делаем систему вложенных циклов. Проходимся сперва по ученикам, а потом по оценкам с занятий каждого ученика.

    • В цикле по занятиям собираем общие баллы по каждой активности, чтобы потом рассчитать рейтинг.

    • После прохождения по всем занятиям собираем рейтинг ученика и проверяем, попал ли он в топ-3.

    • И ещё считаем, не обновился ли минимальный и максимальный рейтинг.

  3. А в конце, уже после прохождения в цикле по всем ученикам, досчитываем оставшиеся показатели: средний рейтинг (потому что для него нужно посчитать сумму рейтингов по всем ученикам) и вердикт по программе.

Как считать данные, разделённые пробелом или запятой, из одной строки?

Загляните в раздел «Формулировка задачи». После формулировки задачи ниже в блоке «Обратите внимание» разобрали вопрос.

Как считать все входные данные в задаче?

Проанализируйте структуру входных данных. Определите, какие элементы уникальные, а какие повторяющиеся. Уникальные элементы считайте разово. Повторяющиеся элементы считайте с помощью цикла.

Структура входных данных задачи:

  1. Строчка с общими данными (уникальный)
  2. Блок с данными об учениках и их результатах обучения (повторяющийся)
    • Фамилия ученика
    • Блок с перечнем оценок по каждому занятию (повторяющийся)
Не понимаю, как рассчитать рейтинги трёх лучших учеников?

Можете воспользоваться следующим алгоритмом.

Ключевая идея: каждый раз, когда рассчитываем рейтинг нового ученика в цикле, проверяем, входит он в топ-3 по рейтингу или нет. В результате, когда считаем данные всех учеников, мы получим финальный топ-3 лучших по рейтингу.

С топ-3 нового ученика на каждой итерации цикла можете сравнивать следующим образом:

  1. Если рейтинг нового ученика выше первого места — рейтинг нового ученика ставим на первое место. Остальных смещаем на одну позицию вниз.
  2. Если ниже первого места, но выше второго — ставим на второе место. Всех, кроме первого, смещаем на одну позицию вниз.
  3. Если ниже второго места, но выше третьего — ставим на третье место.
  4. Если ниже третьего места — ничего не меняем.
Как рассчитывается рейтинг ученика?

Рейтинг формируется из сумм оценок по каждому занятию по активностям, взятым с определённым весом (коэффициентом).

Рейтинг ученика = Сумма баллов по всем занятиям

Баллы за одно занятие = (
Оценка за активность x Коэффициент за активность
+ Оценка за практику x Коэффициент за практику
+ Оценка за домашнюю работу x Коэффициент за домашнюю работу
+ Оценка за контрольную работу x Коэффициент за контрольную работу
)

Рекомендуем посмотреть подробнее описание переменных и другие важные детали в разделе «Формулировка задачи»

Как вывести данные в нужном формате?

Воспользуйтесь f-строками, с ними вы встречались в статье о вводе и выводе данных. Они позволяют упростить вывод, когда нужно вывести несколько разных переменных.

Ещё рекомендуем обратить внимание на вывод текста в несколько строчек с помощью """.

Рассмотрим следующий код.

text = """Это первая строка.
Это вторая строка.
А вот и третья!"""
print(text)

Результат работы кода ниже. Благодаря обрамлению текста с помощью трёх кавычек мы поясняем компилятору, что нужно сделать многострочный вывод.

Это первая строка.
Это вторая строка.
А вот и третья!
Как использовать функцию round() для округления?

Функция round() позволяет округлять числа по правилу round-half-to-even (половинки до ближайшего чётного числа). Это означает, что числа вида x.5 округляются к ближайшему чётному числу. А в остальном как обычное математическое округление.

Она поддерживает два формата вызова:

  1. round(число, [количество знаков]) — округляет число, оставляя определённое количество знаков после запятой.
  2. round(число) — если второй аргумент отсутствует, то округляет до ближайшего целого числа по правилу round-half-to-even.

Ниже приведены примеры использования функции.

round(4.7)        # 5
round(4.3)        # 4
round(3.14159, 2) # 3.14

# Примеры поведения на .5
round(2.5)        # 2  (к ближайшему чётному)
round(3.5)        # 4  (к ближайшему чётному)
round(32.5)       # 32 (а не 33!)

В следующих главах вы познакомитесь с инструментами, которые позволят реализовать полный аналог математического округления — math.ceil или math.floor. Или с использованием типа Decimal.

Можно ли упростить ввод данных и заранее их задать для проверки работоспособности программы?

В Python можно заранее задать какой ввод будет у программы. Подробнее как это работает вы изучите в третьем разделе, а пока расскажем об инструменте без детального погружения — для общего развития.

Ниже — пример конструкции, который фиксирует конкретные входные данные. И вам не придётся вбивать их ручками в консоли. Добавьте этот кусок кода в начало программы.

import io, sys

input_data = """\
4 5 190 1 2 4 6
Иванов
0,2,2,3
3,3,3,3
3,2,2,1
0,3,3,3
0,3,3,1
"""
sys.stdin = io.StringIO(input_data)

Изменяя данные в input_data, вы настраиваете необходимый ввод. В данном случае фиксируются следующие входные данные:

4 5 190 1 2 4 6
Иванов
0,2,2,3
3,3,3,3
3,2,2,1
0,3,3,3
0,3,3,1

Обратите внимание. Символ «\» в начале текст input_data обязателен. С помощью него первой строчкой сразу идут данные «4 5 190 1 2 4 6». Если бы он отсутствовал, то первой строчкой у вас была бы пустая строка.

Этот приём можете применять не только для решения этой задачи, но и тестирования задач в параграфах.

Если читаете этот текст — значит, у вас получилось справиться с задачами или возникли трудности. В любом случае вы взялись за эту задачу — а это похвально!

Ниже найдёте код автора. Изучите его и сравните со своим решением. А ещё ниже автор описал размышления о подходе к задаче и разобрал каждый кусочек кода. Загляните в блоки, к которым остались вопросы или в которых увидели новые элементы решения.

Разбор

Посмотреть решение задачи 1 «Считывание параметров для анализа»
(
    num_students, num_lessons, max_rating,
    classwork_coefficient, selfwork_coefficient, homework_coefficient, testwork_coefficient
) = map(int, input().split())  # Считываем параметры курса

print(f"""{num_lessons}
{num_students}
{classwork_coefficient}
{selfwork_coefficient}
{homework_coefficient}
{testwork_coefficient}
{max_rating}""")
Посмотреть решение задачи 2 «Рейтинг ученика»
# Считываем параметры курса
(
    num_students, num_lessons, max_rating,
    classwork_coefficient, selfwork_coefficient, homework_coefficient, testwork_coefficient
) = map(int, input().split())

# Проверяем корректность параметров
if (
    num_lessons > 0 and
    classwork_coefficient > 0 and
    selfwork_coefficient > 0 and
    homework_coefficient > 0 and
    testwork_coefficient > 0
):
    student_lastname = input().strip()  # фамилия ученика

    # Инициализация сумм оценок
    classwork_sum = 0
    selfwork_sum = 0
    homework_sum = 0
    testwork_sum = 0

    # Считываем M строк с оценками
    for _ in range(num_lessons):
        classwork, selfwork, homework, testwork = map(int, input().split(","))
        classwork_sum += classwork
        selfwork_sum += selfwork
        homework_sum += homework
        testwork_sum += testwork

    # Рассчитываем рейтинг
    rating = (
        classwork_sum * classwork_coefficient +
        selfwork_sum * selfwork_coefficient +
        homework_sum * homework_coefficient +
        testwork_sum * testwork_coefficient
    )

    # Проверяем, не превышает ли рейтинг максимальный
    if rating > max_rating:
        print("Во введённых данных ошибка")
    else:
        percent = round(rating * 100 / max_rating)
        print(f"{student_lastname} {percent}%")
else:
    print("Во введённых данных ошибка")
Посмотреть решение задачи 3 «Анализ качества образовательной программы»
(
    num_students, num_lessons, max_rating,
    classwork_coefficient, selfwork_coefficient, homework_coefficient, testwork_coefficient
) = map(int, input().split())  # Считываем параметры курса

# Проверяем корректность входных данных
if (
        num_students >= 3 and  # Минимум 3 ученика
        num_lessons > 0 and    # Должно быть хотя бы одно занятие
        classwork_coefficient > 0 and
        selfwork_coefficient > 0 and
        homework_coefficient > 0 and
        testwork_coefficient > 0 and
        max_rating > 0         # Максимальный рейтинг должен быть положительным
):
    # Инициализация переменных для поиска топ-3 учеников и расчёта рейтинга программы
    max_rating_abs = 0
    max_rating_abs2 = 0
    max_rating_abs3 = 0
    student1_lastname = None
    student2_lastname = None
    student3_lastname = None

    sum_rating_abs = 0
    min_rating_abs = max_rating

    # Обрабатываем данные по каждому ученику
    for _ in range(num_students):
        student_lastname = input()  # Считываем фамилию ученика

        # Инициализируем суммарные баллы за разные виды работ
        classwork_sum = 0
        homework_sum = 0
        selfwork_sum = 0
        testwork_sum = 0

        # Считываем оценки по каждому занятию
        for i in range(num_lessons):
            classwork, selfwork, homework, testwork = map(int, input().split(","))
            classwork_sum += classwork
            selfwork_sum += selfwork
            homework_sum += homework
            testwork_sum += testwork

        # Рассчитываем итоговый рейтинг ученика
        rating = (
                classwork_sum * classwork_coefficient +
                homework_sum * homework_coefficient +
                selfwork_sum * selfwork_coefficient +
                testwork_sum * testwork_coefficient
        )

        # Обновляем топ-3 учеников
        if rating > max_rating_abs:
            max_rating_abs3 = max_rating_abs2
            student3_lastname = student2_lastname
            max_rating_abs2 = max_rating_abs
            student2_lastname = student1_lastname
            max_rating_abs = rating
            student1_lastname = student_lastname
        elif rating > max_rating_abs2:
            max_rating_abs3 = max_rating_abs2
            student3_lastname = student2_lastname
            max_rating_abs2 = rating
            student2_lastname = student_lastname
        elif rating > max_rating_abs3:
            max_rating_abs3 = rating
            student3_lastname = student_lastname

        # Обновляем минимальный рейтинг
        if rating < min_rating_abs:
            min_rating_abs = rating
        sum_rating_abs += rating  # Добавляем рейтинг ученика в суммарный

    # Проверяем, не превышает ли максимальный рейтинг допустимое значение
    if max_rating_abs > max_rating:
        print("Во введённых данных ошибка")
    else:
        # Вычисляем максимальный, средний и минимальный рейтинг в процентах
        max_rating_perc = round(max_rating_abs * 100 / max_rating)
        avg_rating_perc = round((sum_rating_abs / num_students) * 100 / max_rating)
        min_rating_perc = round(min_rating_abs * 100 / max_rating)

        # Определяем, насколько хорошо усваивается курс
        if avg_rating_perc > 50:
            verdict = "Курс усваивается хорошо"
        else:
            verdict = "Курс усваивается плохо"

        # Выводим результаты
        print(f"""{max_rating_perc} {avg_rating_perc} {min_rating_perc}
{student1_lastname} {round(max_rating_abs * 100 / max_rating)}%
{student2_lastname} {round(max_rating_abs2 * 100 / max_rating)}%
{student3_lastname} {round(max_rating_abs3 * 100 / max_rating)}%
{verdict}
        """)
else:
    print("Во введённых данных ошибка")  # Ошибка при некорректных входных данных

Подход к задаче

Первым шагом внимательно читаем задачу и вычленяем ключевые моменты. Правильно понятая задача — это половина успеха. Что можно в ней выделить:

Входные данные имеют конкретную структуру
  1. Одна строчка с общими параметрами.
  2. Перечень учеников с оценками в определённом формате (фамилия + оценки за занятия).
  3. Определённое количество строчек приходится на каждого ученика.

Итого

Сначала будем считывать общие параметры, а затем с помощью вложенных циклов проходиться по каждому ученику и в нём по каждому занятию.

Нас просят рассчитать максимальный, минимальный и усреднённый рейтинг учеников

Данные для текущего максимального, минимального и усреднённого рейтинга необходимо сохранять после прохода по каждому ученику в рамках цикла.

Усреднённый рейтинг = сумма всех рейтингов / количество учеников. Количество учеников мы знаем, сумму всех рейтингов нужно будет дополнительно просчитывать.

Итого

После прохода по каждому ученику мы пересчитываем максимальный, минимальный рейтинг и сумму всех рейтингов.

Также нужно вывести топ-3 учеников по рейтингу

После прохода в цикле по ученику мы получаем его рейтинг.

Этот рейтинг сравниваем с текущим топ-3. И если ученик входит в тройку лидеров, то пересчитываем топ-3.

Итого

После прохода по каждому ученику мы храним текущий топ-3.

Сделать вывод, насколько усваивается курс

Итого

Среднее значение получим только после прохода по всем ученикам. Тогда и сделаем вывод.

Дополнительно учесть ограничения по вводимым данным

А именно:

  1. Количество учеников больше 3 (N>3), количество занятий — 1 и больше (M>0), коэффициенты учёта всех активностей больше 0 (cw, sw, hw, tw >0) — эти условия можно проверить сразу на этапе счёта первой строчки.
  2. Рассчитанный максимальный рейтинг ученика на программе не должен превышать Q — сможем проверить это уже после прохода по всем ученикам.
  3. При этом если Q<0, то изначальное условие уже не выполнится. Поэтому можем включить эту проверку на этапе счёта первой строчки.

Итого

Большинство проверок делаем сразу при счёте первой строчки. Проверку на максимальный рейтинг делаем после прохода по всем ученикам.

После анализа задачи вторым шагом накидываем примерный подход к решению.

И последним шагом ещё раз проверяем наш подход/алгоритм, читая условие. Ничего ли мы не забыли? Вроде ничего. Теперь можно приступать к написанию кода.

Считывание входных данных

Заметим, что считывание отдельных данных из строчки ещё не проходили. Для этого в описании задачи и в подсказке описали использование функции map() с методом .split().

Для считывания первой строчки данных используем код:

(
    num_students, num_lessons, max_rating,
    classwork_coefficient, selfwork_coefficient, homework_coefficient, testwork_coefficient
) = map(int, input().split())  # Считываем параметры курса

Этот код считывает первую строчку ввода, содержащую основные параметры курса, и присваивает их соответствующим переменным.

Представим, что на вход в этой задаче в первой строчке получаем:

4 5 190 1 2 4 6

Здесь:

  • 4 – количество учеников (num_students)
  • 5 – количество занятий (num_lessons)
  • 190 – максимальный возможный рейтинг (max_rating)
  • 1 2 4 6 – коэффициенты за разные виды работы (classwork_coefficient, selfwork_coefficient, homework_coefficient, testwork_coefficient)

Тогда input считает ввод как полную строчку.

“4 5 190 1 2 4 6”

Метод .split() разделяет строку по пробелам, превращая её в набор отдельных строчных элементов.

[“4”, “5”, “190”, “1”, “2”, “4”, “6”]

map(int, input().split()) применяет функцию int() ко всем элементам списка, превращая их из строк в числа.

[4, 5, 190, 1, 2, 4, 6]

А после выполнения:

(
    num_students, num_lessons, max_rating,
    classwork_coefficient, selfwork_coefficient, homework_coefficient, testwork_coefficient
) = map(int, input().split())  # Считываем параметры курса

Переменные получают значения:

num_students = 4
num_lessons = 5
max_rating = 190
classwork_coefficient = 1
selfwork_coefficient = 2
homework_coefficient = 4
testwork_coefficient = 6

Каждое число разбирается и попадает в свою переменную.

Таким же образом мы будем считывать данные для оценок по занятиям.

Расчёт необходимых показателей

Показатели, которые нам нужно рассчитать:

  • Общие параметры программы в процентах:
    • максимальный (max_rating_perc)

    • средний (avg_rating_perc)

    • и минимальный рейтинг (min_rating_perc)

  • Топ-3 учеников по рейтингу с фамилиями:
    • Топ-1 (max_rating_abs, student1_lastname)

    • Топ-2 (max_rating_abs2, student2_lastname)

    • Топ-3 (max_rating_abs3, student3_lastname)

  • Насколько усваивается программа:
    • Вердикт (verdict)

Рассчитывать эти показатели будем, проходясь в рамках вложенного цикла по ученикам и по их занятиям. Полный код, который собирает всё необходимое, структурно выглядит так.

# Инициализация переменных для поиска топ-3 учеников и расчёта рейтинга программы
…

# Обрабатываем данные по каждому ученику
for _ in range(num_students):

    # Инициализируем суммарные баллы за разные виды работ
    …

    # Считываем оценки по каждому занятию
    for i in range(num_lessons):
        …
   
   # Рассчитываем итоговый рейтинг ученика
    …

    # Обновляем топ-3 учеников
    …

    # Обновляем рейтинги
    …

# Определяем, насколько хорошо усваивается курс
…

Получается, что всё основное рассчитывается в цикле прохождения по ученикам. А цикл для занятий нужен только для того, чтобы посчитать потом всё нужное в рамках цикла по ученикам. Далее пройдёмся по каждому логическому блоку.

Инициализация переменных для поиска топ-3 учеников и расчёта рейтинга программы

Основная задача блока — обозначить переменные для расчётов, чтобы не возникали лишние ошибки во время обработки данных. Инициализируем их перед циклом по ученикам, так как в этом цикле будут идти уже расчёты.

# Инициализация переменных для поиска топ-3 учеников и расчёта рейтинга программы 
max_rating_abs = 0
max_rating_abs2 = 0
max_rating_abs3 = 0
student1_lastname = None
student2_lastname = None
student3_lastname = None

sum_rating_abs = 0
min_rating_abs = max_rating

# Обрабатываем данные по каждому ученику
for _ in range(num_students):
…

В данном случае обрабатываем всё, что нужно для вывода топ-3 учеников и расчёта рейтинга:

  • Топ-1. Рейтинг и фамилия (max_rating_abs, student1_lastname).
  • Топ-2. Рейтинг и фамилия (max_rating_abs2, student2_lastname).
  • Топ-3. Рейтинг и фамилия (max_rating_abs3, student3_lastname).
  • Суммарный рейтинг (sum_rating_abs).
  • Минимальный рейтинг на программе (min_rating_abs).
Инициализируем суммарные баллы за разные виды работ

Основная задача блока такая же, как и в предыдущем — обозначить переменные для расчётов, чтобы не возникали лишние ошибки во время обработки данных. Инициализируем их перед циклом по ученикам, так как в этом цикле будут уже идти расчёты.

# Инициализируем суммарные баллы за разные виды работ
classwork_sum = 0
homework_sum = 0
selfwork_sum = 0
testwork_sum = 0

# Считываем оценки по каждому занятию
for i in range(num_lessons):
…

В данном случае обрабатываем всё, что нужно для расчёта промежуточных значений для рейтинга. Эти значения будут считаться в цикле по заданиям:

  • Сумма баллов за активность на занятии (classwork_sum).
  • Сумма баллов за практику (homework_sum).
  • Сумма баллов за домашние задания (selfwork_sum).
  • Сумма баллов за контрольные работы (testwork_sum).
Считываем оценки по каждому занятию

Основная задача блока — посчитать всё необходимое для расчёта рейтинга ученика.

student_lastname = input()  # Считываем фамилию ученика        
        
# Считываем оценки по каждому занятию
for i in range(num_lessons):
   classwork, selfwork, homework, testwork = map(int, input().split(","))
   classwork_sum += classwork
   selfwork_sum += selfwork
   homework_sum += homework
   testwork_sum += testwork

Если вспомним ввод, то сейчас для каждого ученика он подаётся в следующем виде:

Иванов
2,3,0,0
0,4,0,1
0,0,9,0
0,3,0,0
4,0,0,2

В рамках кода мы сначала считываем фамилию ученика. Просто через input(). Таким образом в student_lastname улетит «Иванов».

student_lastname = input()  # Считываем фамилию ученика  

Затем мы считываем оценки за занятие. С помощью функции map() и метода .split(). Так же, как мы считывали первую строчку.

classwork, selfwork, homework, testwork = map(int, input().split(","))

Таким образом, в рамках прохода по первому занятию:

classwork = 2
selfwork = 3
homework = 0
testwork = 0

И в заключении мы подсчитываем, сколько суммарно баллов ученик получил за каждую из активностей.

Здесь используется сокращенный формат суммирования, который значит следующее:

classwork_sum += classwork      
# Это то же самое, что classwork_sum = classwork_sum + classwork
classwork_sum += classwork
selfwork_sum += selfwork
homework_sum += homework
testwork_sum += testwork

То есть после прохождения по первой строчке значения в переменных будут:

classwork_sum = 2
selfwork_sum = 3
homework_sum = 0
testwork_sum = 0

А после прохождения всего цикла по заданному ученику:

classwork_sum = 2 + 0 + 0 + 0 + 4 = 6
selfwork_sum = 3 + 4 + 0 + 3 + 0 = 10
homework_sum = 0 + 0 + 9 + 0 + 0 = 9
testwork_sum = 0 +1 + 0 + 0 + 2 = 3

Эти данные используются уже для расчёта рейтинга: попал ли текущий ученик в топ-3.

Рассчитываем итоговый рейтинг ученика

Основная задача блока — посчитать рейтинг ученика по предложенной в задаче формуле.

В условии задачи формула описывалась как сумма баллов за все занятия.

Рейтинг ученика = Сумма баллов по всем занятиям

Баллы за одно занятие = (
Оценка за активность x Коэффициент за активность
+ Оценка за практику x Коэффициент за практику
+ Оценка за домашнюю работу x Коэффициент за домашнюю работу
+ Оценка за контрольную работу x Коэффициент за контрольную работу
)

Можете заметить, что при расчёте баллов за каждое занятие оценки умножаются на одни и те же коэффициенты. Тогда может организовать расчёт по-другому? Например, просуммировать все оценки за каждую активность.

Рейтинг ученика = (
Сумма всех оценок за активность x Коэффициент за активность
+ Сумма всех оценок за практику x Коэффициент за практику
+ Сумма всех оценок за домашние x Коэффициент за домашние
+ Сумма всех оценок за контрольные x Коэффициент за контрольные
)

В коде эта формула выглядит почти так же. Единственное, обратите внимание, что мы не записываем всю формулу в одну строчку, а раскидываем разные элементы счёта на разные строчки. Так проще увидеть сразу логику расчётов.

# Рассчитываем итоговый рейтинг ученика
rating = (
        classwork_sum * classwork_coefficient +
        homework_sum * homework_coefficient +
        selfwork_sum * selfwork_coefficient +
        testwork_sum * testwork_coefficient
)

Возьмём данные по Иванову, полученные в прошлом блоке. Его рейтинг при коэффициентах 1, 2, 4, 6 будет:

rating = (6 * 1 + 10 * 2 + 9 * 4 + 3 * 4) = 6 + 20 + 36 + 12 = 74
Обновляем топ-3 учеников

Основная задача блока — после прохода по циклу по каждому ученику держать актуальным текущий топ-3 учеников. Тогда после прохождения по всем ученикам финальный топ-3 будет нужным результатом.

Ранее мы уже инициировали переменные, которые относятся к топ-3 учеников:

# Инициализация переменных для поиска топ-3 учеников и расчёта рейтинга программы 
max_rating_abs = 0
max_rating_abs2 = 0
max_rating_abs3 = 0
student1_lastname = None
student2_lastname = None
student3_lastname = None

Теперь нам нужно реализовать функционал, который поможет определить, входит ли новый student_lastname и rating в топ-3 и на каком он месте. Код для решения этой задачи следующий:

# Обновляем топ-3 учеников
if rating > max_rating_abs:
    max_rating_abs3 = max_rating_abs2
    student3_lastname = student2_lastname
    max_rating_abs2 = max_rating_abs
    student2_lastname = student1_lastname
    max_rating_abs = rating
    student1_lastname = student_lastname
elif rating > max_rating_abs2:
    max_rating_abs3 = max_rating_abs2
    student3_lastname = student2_lastname
    max_rating_abs2 = rating
    student2_lastname = student_lastname
elif rating > max_rating_abs3:
    max_rating_abs3 = rating
    student3_lastname = student_lastname

С помощью условий мы пошагово проверяем:

  • рейтинг текущего ученика больше рейтинга первого места или нет;
  • если нет, то больше ли второго;
  • если нет, то больше ли третьего.

И если окажется, что рейтинг текущего ученика больше рейтинга одного из мест топ-3, то он заменяет ученика, находящегося на этом месте, и всех, кто дальше, сдвигает на позицию вниз.

То есть если только что проверенный ученик пришёл на первое место,
то первое место ушло на второе, второе — на третье. А третье место ушло из топ-3, потому что стало четвёртым.

А если только что проверенный ученик пришёл на второе место,
то первое место осталось неизменным, второе место ушло на третье. А третье место ушло из топ-3, потому что стало четвёртым.

А если только что проверенный ученик пришёл на третье место,
то первое и второе место остались неизменными. Третье место ушло из топ-3, потому что стало четвёртым.

Если ученик оказался по рейтингу ниже третьего места,
то он никак не повлиял на текущее распределение.

Обновляем рейтинги

Основная задача блока — посчитать разброс рейтинга и среднее значение в процентах. Минимальное значение обновляем в рамках цикла, максимальное значение рейтинга — это рейтинг топ-1 ученика. Среднее значение рассчитываем уже после прохождения в цикле по всем ученикам.

# Обрабатываем данные по каждому ученику
for _ in range(num_students):        
    …
       
    # Обновляем минимальный рейтинг
    if rating < min_rating_abs:
        min_rating_abs = rating
    sum_rating_abs += rating  # Добавляем рейтинг ученика в суммарный

    …

# Вычисляем максимальный, средний и минимальный рейтинг в процентах
max_rating_perc = round(max_rating_abs * 100 / max_rating)
avg_rating_perc = round((sum_rating_abs / num_students) * 100 / max_rating)
min_rating_perc = round(min_rating_abs * 100 / max_rating)

Чтобы получить минимальный рейтинг:

  • После каждого прохождения в цикле проверяем, рейтинг текущего ученика ниже минимального или нет?
  • Стартовым значением min_rating_abs мы объявили max_rating, которое подаётся в первой строчке данных. Таким образом, первый рейтинг ученика точно будет ниже его.

Чтобы получить максимальный рейтинг:

  • А он у нас уже есть. Это рейтинг топ-1 max_rating_abs

Чтобы получить средний рейтинг:

  • Вспомним, что средний рейтинг = суммарный рейтинг / количество учеников.
  • Суммарный рейтинг sum_rating_abs считаем в цикле и постоянно обновляем его.
  • Количество учеников знаем из вводных данных из первой строчки.

Также нас попросили рассчитать рейтинги в процентах от максимально возможного и округлить до целого.

  • Чтобы получить процент, умножаем на 100
  • А чтобы округлить, используем функцию округления round(), которая работает почти как математическое округление. Подробнее детали работы функции round() рассмотрели в подсказке.
round (число, [количество знаков])
round (4.7)     #5
round (4.3)     #4
round (3.14159, 2)    #3.14 (оставили 2 знака)

Полноценная формула для расчёта рейтинга с учётом вышесказанного будет выглядеть так:

# Вычисляем максимальный, средний и минимальный рейтинг в процентах
max_rating_perc = round(max_rating_abs * 100 / max_rating)
avg_rating_perc = round((sum_rating_abs / num_students) * 100 / max_rating)
min_rating_perc = round(min_rating_abs * 100 / max_rating)
Определяем, насколько хорошо усваивается курс

Основная задача блока — вынести конкретный вердикт на вопрос «Насколько хорошо усваивается курс?». В целом все данные у нас уже посчитаны, надо только сравнить с определённым процентом.

# Определяем, насколько хорошо усваивается курс
if avg_rating_perc > 50:
    verdict = "Курс усваивается хорошо"
else:
    verdict = "Курс усваивается плохо"

Проверка данных на валидность

Небольшим нововведением для этой задачи стал запрос проверки данных на определённые граничные условия. В рамках кода дважды проверяем соответствие граничным условиям, чтобы в случае несоответствия вывести ошибку.

Первый раз проверяем, когда получаем на вход первую строчку со всеми общими параметрами.

(
    num_students, num_lessons, max_rating,
    classwork_coefficient, selfwork_coefficient, homework_coefficient, testwork_coefficient
) = map(int, input().split())  # Считываем параметры курса

# Проверяем корректность входных данных
if (
        num_students >= 3 and  # Минимум 3 ученика
        num_lessons > 0 and    # Должно быть хотя бы одно занятие
        classwork_coefficient > 0 and
        selfwork_coefficient > 0 and
        homework_coefficient > 0 and
        testwork_coefficient > 0 and
        max_rating > 0         # Максимальный рейтинг должен быть положительным
):
       …
       …
else:
    print("В введённых данных ошибка")  # Ошибка при некорректных входных данных

Что проверяем:

  1. Количество учеников больше или равно 3 (num_students >= 3).
  2. Должно быть хотя бы одно занятие (num_lessons > 0).
  3. Коэффициенты активностей оценки должны быть больше нуля.
  4. Добавочное условие — максимальный рейтинг должен быть положительным (max_rating). Без этого условия программа всё равно будет работать и выдавать правильный результат, но таким образом не запускаем все просчёты при точно неправильном случае.

Второй раз проверяем, когда уже прошлись по всем ученикам и рассчитали максимальный рейтинг среди учеников. Проверяем, что максимальный рейтинг среди учеников ниже максимально возможного рейтинга.

# Проверяем, не превышает ли максимальный рейтинг допустимое значение
if max_rating_abs > max_rating:
    print("В введённых данных ошибка")
else:
    # Вычисляем максимальный, средний и минимальный рейтинг в процентах
    max_rating_perc = round(max_rating_abs * 100 / max_rating)
    avg_rating_perc = round((sum_rating_abs / num_students) * 100 / max_rating)
    min_rating_perc = round(min_rating_abs * 100 / max_rating)

Вывод данных

В данной задаче просят вывести много данных и подготовить их.

# Выводим результаты
print(f"""{max_rating_perc} {avg_rating_perc} {min_rating_perc}
{student1_lastname} {round(max_rating_abs * 100 / max_rating)}%
{student2_lastname} {round(max_rating_abs2 * 100 / max_rating)}%
{student3_lastname} {round(max_rating_abs3 * 100 / max_rating)}%
{verdict}
""")

Для вывода воспользовались:

  1. f-строками, чтобы могли просто подставлять переменные напрямую в код вывода: {max_rating_perc} {avg_rating_perc} {min_rating_perc} и так далее
  2. И воспользовались тремя кавычками """…. """, чтобы вывести текст на несколько строк. Так код получается чище. Не нужно добавлять \n и использовать + для объединения строк.

Перечень тестов для проверки

После того как написали код, надо продумать, как будем его проверять, чтобы точно убедиться, что задача решена.

Для этого сформулируем набор тестов, которые затрагивают крайние случаи и позволяют проверить все возможные ошибки. Варианты тестов для текущей задачи представлены в таблице.

Описание теста

Что хотим проверить

Любые рассчитываемые данные

Работу базового алгоритма

Num_students = 3, у двоих одинаковый рейтинг

Обработку крайних значений, при равенстве

Num_students = 2

Крайние случаи

Max_rating получился меньше, чем рейтинг у учеников

Крайние случаи

Пара значений из первой строчки отрицательные

Крайние случаи

На вход даём 30+ фамилий

Полноценный тест работоспособности расчётов

Примеры для тестов:

Входные данные:

3 5 300 3 4 7 8
Иванов
5,7,0,0
0,4,0,0
0,0,9,0
7,8,0,0
0,0,0,9
Петров
0,10,0,0
2,10,0,0
0,0,10,0
8,9,0,0
0,0,0,10
Кузнецов
0,7,0,0
5,6,0,0
0,0,9,0
8,8,0,0
0,0,0,9

Выходные данные:

99 89 82
Петров 99%
Кузнецов 86%
Иванов 82%
Курс усваивается хорошо

Входные данные:

3 4 100 1 2 3 4
Иванов
5,0,0,0
4,0,0,0
0,0,6,0
0,0,0,10
Петров
6,0,0,0
5,0,0,0
0,0,7,0
0,0,0,9
Сидоров
7,0,0,0
5,0,0,0
0,0,8,0
0,0,0,8

Выходные данные:

68 68 67
Петров 68%
Сидоров 68%
Иванов 67%
Курс усваивается хорошо

Входные данные:

2 4 200 1 2 3 4
Иванов
5,0,0,0
4,0,0,0
0,0,6,0
0,0,0,10
Петров
6,0,0,0
5,0,0,0
0,0,7,0
0,0,0,9

Выходные данные:

Во введённых данных ошибка

Входные данные:

3 3 50 1 2 3 4
Иванов
5,0,0,0
0,0,10,0
0,0,0,15
Петров
6,0,0,0
0,0,9,0
0,0,0,14
Сидоров
7,0,0,0
0,0,8,0
0,0,0,13

Выходные данные:

Во введённых данных ошибка

Входные данные:

-3 -3 50 1 1 2 3
Иванов
5,0,0,0
0,0,6,0
0,0,0,9
Петров
5,0,0,0
0,0,8,0
0,0,0,9
Сидоров
6,0,0,0
0,0,7,0
0,0,0,10

Выходные данные:

Во введённых данных ошибка
На вход даём 30+ фамилий

Входные данные

35 3 150 1 1 2 4
Иванов
5,0,0,0
0,0,10,0
0,0,0,12
Петров
6,0,0,0
0,0,8,0
0,0,0,14
Сидоров
4,0,0,0
0,0,9,0
0,0,0,10
Смирнов
3,0,0,0
0,0,7,0
0,0,0,11
Кузнецов
7,0,0,0
0,0,6,0
0,0,0,9
Попов
6,0,0,0
0,0,8,0
0,0,0,13
Васильев
5,0,0,0
0,0,5,0
0,0,0,8
Павлов
4,0,0,0
0,0,9,0
0,0,0,10
Семенов
3,0,0,0
0,0,6,0
0,0,0,9
Голубев
8,0,0,0
0,0,4,0
0,0,0,7
Воробьев
5,0,0,0
0,0,10,0
0,0,0,15
Федоров
4,0,0,0
0,0,5,0
0,0,0,6
Михайлов
6,0,0,0
0,0,9,0
0,0,0,12
Тихонов
3,0,0,0
0,0,6,0
0,0,0,10
Беляев
7,0,0,0
0,0,7,0
0,0,0,9
Тимофеев
5,0,0,0
0,0,5,0
0,0,0,7
Антонов
6,0,0,0
0,0,8,0
0,0,0,11
Никитин
5,0,0,0
0,0,9,0
0,0,0,14
Тарасов
4,0,0,0
0,0,6,0
0,0,0,8
Гаврилов
3,0,0,0
0,0,5,0
0,0,0,7
Романов
7,0,0,0
0,0,9,0
0,0,0,10
Королев
5,0,0,0
0,0,7,0
0,0,0,9
Захаров
4,0,0,0
0,0,6,0
0,0,0,8
Алексеев
6,0,0,0
0,0,8,0
0,0,0,11
Егоров
5,0,0,0
0,0,9,0
0,0,0,12
Богданов
4,0,0,0
0,0,5,0
0,0,0,6
Денисов
6,0,0,0
0,0,7,0
0,0,0,10
Киселев
5,0,0,0
0,0,9,0
0,0,0,13
Макаров
4,0,0,0
0,0,6,0
0,0,0,8
Орлов
3,0,0,0
0,0,5,0
0,0,0,7
Герасимов
7,0,0,0
0,0,9,0
0,0,0,11
Федотов
5,0,0,0
0,0,7,0
0,0,0,9
Калинин
4,0,0,0
0,0,6,0
0,0,0,8
Афанасьев
5,0,0,0
0,0,9,0
0,0,0,13
Штенцова
6,0,0,0
0,0,7,0
0,0,0,10

Выходные данные:

57 39 25
Воробьев 57%
Никитин 53%
Петров 52%
Курс усваивается плохо

Подводя итог

Если получилось дотошно вникнуть в решение автора, то вы повторили пройденные темы и узнали полезные фишечки. Светлана, автор, тоже подводит итог и делится несколькими пожеланиями на будущее по итогам разбора.

Светлана Овсянникова

Светлана Овсянникова
Ex-разработчик в Яндекс Образовании

  • Внимательное чтение задачи или технического задания (ТЗ) — половина результата. Внимательное построчное чтение и продумывание: «Как эта информация влияет на реализацию решения?», «Что нужно не забыть проработать?», «Что важно тому, кто ставит задачу?» — поможет не упустить критичных деталей.

  • Не бойтесь новых подходов и новой информации. Изучение документации, разбор использования функций и т. п. — это часть работы разработчика. Если с чем-то сталкиваетесь впервые, всегда можно посмотреть информацию в интернете, посоветоваться со старшим коллегой или написать в GPT.

  • С каждым шагом, погружаясь в дальнейшие темы хендбука по Python, вы изучите новые подходы, которые упростят и сделают текущий код функциональнее. И уже в следующей теме познакомитесь со списками, которые упрощают хранение и работу с данными. Продолжайте изучать!

А пока давайте подведём итоги: что изучили и что можно взять с собой дальше.

В рамках этой задачи вы освоили:

  • Работу с input() и обработку данных из строк.
  • Использование .split() и map() для преобразования ввода.
  • Циклы for и вложенные циклы для обработки нескольких уровней данных.
  • Использование round() для округления.
  • Использование if, elif, else для принятия решений.
  • f-строки для удобного форматирования вывода. И вывод текста в несколько строк с помощью “””

А дальше делайте свой код более читаемым:

  • Продолжайте давать переменным понятные имена (например sum_rating_abs).
  • Добавляйте комментарии, особенно в сложных местах.
  • Разбивайте код на логические блоки, как в разборе.

На этом освоение раздела завершено. Ещё раз повторим: вы молодец! Не останавливайтесь.