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

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

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

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

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

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

Повторите:

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

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

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

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

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

Желаем удачи!

Чтобы добавить в заметки выделенный текст, нажмите Ctrl + E
Изучить контекстПогружение в условия
Решить задачуПерейти в Яндекс.Контест
Взять подсказкуЕсли возникли сложности
Посмотреть разборПолный разбор экспертом

Быстрая навигация:

От автора

Цитата автора
Аватар Светланы Овсянниковой

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

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

Привет!

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

Нюансы

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Блок

Что хранится

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

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

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

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

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

- Оценки за другие виды деятельности

(на некоторых программах есть дополнительные активности)

- Рейтинги

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

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

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

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

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

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

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

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

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

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

Фидбэк

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

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

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

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

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

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

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

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

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

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

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

Ключевое:

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

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

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

  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

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

1# Ввод данных в одной строке 
2hours, minutes, seconds = map(int, input().split()) 
3
4# Вывод данных 
5print("Часы:", hours) 
6print("Минуты:", minutes) 
7print("Секунды:", seconds)

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

114”, “30”, “45

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

114, 30, 45

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

1hours = 14
2minutes = 30
3seconds = 45

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

14,30,45

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

1# Ввод данных в одной строке 
2hours, minutes, seconds = map(int, input().split(“,”)) 
3
4# Вывод данных 
5print("Часы:", hours) 
6print("Минуты:", minutes) 
7print("Секунды:", seconds)

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

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

Чтобы добавить в заметки выделенный текст, нажмите Ctrl + E
Оцените ясность обучающего материала
Будем признательны, если вы поделитесь своим отзывом по финальной задаче и по блоку «2. Базовые конструкции Python»
Оценка и отзыв не публикуются
Предыдущий параграф2.5. Чему вы научились

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

Следующий параграф3.1. Строки, кортежи, списки

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