Задания по программированию. Разновидности и примеры.

образовательный процесс
программирование
концепт-карта
Дата публикации

28 июля 2022 г.

Далее приведён вольный перевод и конспект одной из глав данной книги. Ссылки на публикации, которые подтверждают эффективность тех или иных типов упражнений приведены там же.

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

Классические задания

Вопрос с множественным выбором

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

В каком порядке будут выполнены действия в данном выражении:

price = addTaxes(cost - discount)
  1. вычитание, вызов функции, присваивание
  2. вызов функции, вычитание, присваивание
  3. вызов функции, затем одновременное присваивание и вычитание
  4. ничего из выше перечисленного

Решение задачи (C&R - Code and Run)

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

Переменная picture содержит информацию об изображении, считанном из файла. Напишите функцию, которая преобразует изображение в чёрно-белое и сохраните результат в переменной monochrome.

Решение задачи можно совместить с ответом на вопрос с несколькими вариантами. В следующем примере не получится правильно ответить на вопрос не выполнив Linux-команду ls в терминале.

Текущий каталог - /home. Какой из перечисленных файлов не находится в данном каталоге?

  1. зима.csv
  2. весна.csv
  3. лето.csv
  4. осень.csv

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

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

Функция monotonic_sum вычисляет сумму каждой “секции” массива чисел в которой числа идут строго по возрастанию. Например для массива [1, 3, 3, 4, 5, 1] функция должна дать следующий результат: [4, 12, 1]. Напишите и запустите тесты с помощью которым можно будет определить, если ли в реализации функции ошибки:

  • включается ли первое число секции в подсумму.
  • включается ли последнее число секции в подсумму.
  • выполняется ли условие, что следующая подсумма вычисляется если предыдущее число равно следующему (строго больше предыдущего).

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

Заполните пропуски в приведённом ниже коде таким образом, чтобы выводилась строка 'грамм':

text = 'программа'
word = text[___:___]
print(word)

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

Расставьте приведённые строки кода в таком порядке, чтобы полученная программа считала сумму положительных чисел в массиве (отступы и двоеточия вам необходимо расставить самостоятельно).

total = 0
if v > 0
total += v
for v in values

N.B. Отступы обязательно необходимы при программировании на Python. В случае с языками, где используются операторные скобки (begin...end, {...}) нужно указать, что учащимся требуется добавить их самостоятельно.

Для усложнения задачи можно дать учащимся лишние строки кода, или попросить добавить недостающие строки самостоятельно.

Трассировка программ

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

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

vals = [-1, 0, 1]     # а)
inverse_sum = 0        # б)
try:
    for v in vals:
        inverse_sum += 1/v    # в)
except:
    pass    # г)

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

Какие значения будут принимать переменные left и right в процессе выполнения данной программы?

left = 23
right = 6
while right:
    left, right = right, left % right
Шаг left right
1
2
3

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

Какое пропущенное значение в матрице values приведёт к ошибке в выполнении программы?

values = [ [1.0, -0.5], [3.0, 1.5], [2.5, ___] ]
runningTotal = 0.0
for (reading, scaling) in values:
    runningTotal += reading / scaling

Использование диаграмм

Рисование студентами диаграмм и концепт-карт позволяет получить представление об их мышлении. Но нарисованные в произвольной форме диаграммы трудно оценивать.

Вместо этого можно дать задание проставить метки на уже существующей диаграмме.

На рисунке представлен фрагмент HTML-страницы в виде дерева. Расставьте цифры от 1 до 9 на элементах диаграммы, показав в каком порядке они будут пройдены при использовании алгоритма обхода в глубину.

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

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

Из предоставленного набора Scratch-блоков составьте необходимую программу.

Задания с поиском соответствий тоже можно отнести к категории задач с диаграммами.

Сопоставьте оператор регулярного выражения с его назначением:

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

Автоматическое оценивание

Первые программы для автоматической проверки появились в 60-х годах 1.

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

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

Следующий вариант автоматического оценивания - предоставлять учащимся набор тестов, но перед возможностью использовать каждый из них необходимо ответить, каким должны быть выходные данные для предложенных входных. Например необходимо написать функцию, которая найдёт наибольшую сумму пары смежных чисел в массиве. Перед тем как запустить автоматическое тестирование, студенту задаётся вопрос “Какое значение должна вывести функции если передать в неё следующий массив: [4, 3, -1, 5, 3, 3]?” Только после правильно ответа данный тест можно запустить и проверить работу программы.

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

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

Задания повышенной сложности

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

Обзор кода (Code review) - пример задания, в котором учащемуся необходимо найти и указать в коде определённое количество проблем (прим.: нет отступов, некорректное или неподходящее имя переменной и т.д.). Для более продвинутых учащихся список замечаний может быть расширен, и при этом не указано, сколько конкретно проблем в рассматриваемом коде.

Чтобы упростить выполнение такого задания, можно предоставить лист оценивания (rubric).

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

def addem(f):
    x1 = open(f).readlines()
    x2 = [x for x in x1 if x.strip()]
    changes = 0
    for v in x2:
        print('total', total)
        tot = tot + int(v)
        print('total')
  1. плохое имя для переменной (не ясно её назначение)
  2. использование переменной без её определения
  3. значение не возвращается из функции
  4. неиспользованная переменная

Заключение

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

Сноски

  1. Jack Hollingsworth: “Automatic Graders for Programming Classes”. Communications of the ACM, 3(10), 10 1960, doi:10.1145/367415.367422.↩︎