Пример выполнения простого задания: Begin3
На данной странице приводится пошаговое описание процесса решения на языках Ruby и Julia следующего простого задания из группы Begin.
Begin3°. Даны стороны прямоугольника a и b. Найти его площадь S = ab и периметр P = 2(a + b).
Описание ориентировано на версию задачника 4.22, в которой для языков Ruby и Julia
можно использовать среду VS Code (а также среду RubyMine для языка Ruby).
В предыдущих версиях задачника для языка Ruby была доступна также среда NetBeans. При использовании среды NetBeans
проект создавался в специальном подкаталоге PT_Ruby рабочего каталога, причем решение требовалось указывать
в файле с фиксированным именем MyTask.rb, расположенном в этом подкаталоге. В остальном действия при решении
задач на языке Ruby в среде NetBeans незначительно отличались от описываемых далее.
Создание программы-заготовки и знакомство с заданием
Для создания проекта, содержащего заготовку для требуемого задания, следует
воспользоваться программным модулем PT4Load. Для этого достаточно
перейти в рабочий каталог задачника и с помощью ярлыка Load.lnk запустить
программу PT4Load.exe (начиная с версии 4.22, для быстрого запуска любых модулей задачника
можно использовать программу PT4Panel, ярлык которой располагается
на рабочем столе и в любом рабочем каталоге).
В результате на экране появится окно модуля PT4Load,
в котором следует указать
имя нужного задания. Отметим, что в заголовке этого окна указывается имя той программной среды, для которой будет создана заготовка;
при использовании языка Ruby в заголовке должен содержаться текст «Ruby», например, «Visual Studio Code (Ruby)»
(означающий, что заготовка будет создана в редакторе VS Code) или
«RubyMine 2020» (означающий, что заготовка будет создана в среде RubyMine версии 2020).
Созданный проект-заготовка размещается рабочем каталоге задачника
и состоит из нескольких подкаталогов и файлов, однако для решения
задания нам потребуется только один файл с именем Begin3 (и расширением .rb для Ruby и .jl для Julia), который будет автоматически загружен
в редактор среды используемой среды.
Приведем его содержимое (первая строка-комментарий в варианте для языка Ruby
определяет используемую кодировку):
[Ruby]
# coding: utf-8
require "./PT"
def solve()
task "Begin3"
end
start_solve
[Julia]
include("PT.jl")
function solve()
task("Begin3")
end
start_solve()
Файлы Begin3.rb и Begin3.jl содержат описание функции solve, в которой требуется запрограммировать решение
выбранной задачи (хотя, разумеется, в решении
могут использоваться другие функции, описанные в данном файле). Функция solve уже включает вызов
функции task, инициализирующей задание Begin3.
Оператор require обеспечивает подключение кода из файла PT.rb,
включающего вспомогательные функции и классы, необходимые для выполнения заданий. В этом файле,
в частности, описана функция task. Кроме того, в файле PT.rb описана функция start_solve,
вызов которой указывается в конце файла Begin3.rb. В этой функции выполняется инициализация задачника
и тестирование алгоритма, описанного в функции solve. Дополнительные функции и классы для языка Julia
описаны в файле PT.jl, который подключается к файлу Begin3.jl оператором include.
Данную программу уже можно запустить на выполнение. Для этого в среде VS Code достаточно нажать клавишу [F5],
а в среде RubyMine клавишу [Shift]+[F10]. Предусмотрены также кнопки с изображением треугольничка,
позволяющие запустить программу (для отображения этой кнопки в среде VS Code надо предварительно
установить режим отладки, нажав комбинацию [Ctrl]+[Shift]+[D]). Запуск программ можно
ускорить, если отключить режим отладки; для этого достаточно использовать комбинацию [Ctrl]+{F5].
В результате на экране появится окно задачника,
содержащее формулировку задания и пример исходных данных.
Начиная с версии 4.11, окно задачника может отображаться в двух режимах:
с динамической компоновкой, при которой каждый раздел «подстраивается» под свое содержимое,
и с фиксированной компоновкой, при которой каждый раздел имеет фиксированные размеры.
В предыдущих версиях задачника был доступен только режим с фиксированной компоновкой. Режим
с динамической компоновкой особенно удобен для заданий с большими формулировками и большими наборами данных.
Ниже приведены оба режима окна для данного задания при использовании языка Ruby;
вначале указан режим с динамической компоновкой
(для переключения режимов предназначена клавиша [F4]).
Запуск нашей программы был признан ознакомительным (и поэтому правильность решения не анализировалась),
так как в ходе ее выполнения не было совершено ни одной операции ввода-вывода. Для завершения программы
достаточно закрыть окно задачника, нажав клавишу [Esc] или кнопку «Выход (Esc)».
При использовании среды RubyMine для закрытия окна можно также нажимать клавишу [F10],
а при использовании среды VS Code клавишу [F5].
Ввод исходных данных
Приступая к решению задачи, надо прежде всего организовать ввод в программу исходных данных.
В нашем случае
исходными данными являются вещественные числа a и b, определяющие стороны прямоугольника
(в области исходных данных в окне задачника эти числа выделены желтым цветом и снабжены комментариями).
Для ввода исходных данных в нашем случае мы можем использовать функцию get_f,
обеспечивающую ввод вещественных чисел, или «универсальную» функцию get, позволяющую
ввести данные любого типа. Использование «универсальной» функции get
не позволяет задачнику распознать ряд ошибок, связанных с вводом, поэтому при начальном
изучении программирования целесообразнее использовать «специализированные» функции,
каждая из которых предназначена для ввода данных определенного типа. Итак, организуем
ввод данных с помощью функции get_f (здесь и далее будем приводить только текст функции solve):
[Ruby]
def solve()
task "Begin3"
a = get_f
b = get_f
end
[Julia]
function solve()
task("Begin3")
a = get_f()
b = get_f()
end
Повторно запустив программу, мы увидим, что исходные данные изменились.
При каждом запуске генерируется новый набор исходных данных, поэтому для
успешного решения задания необходимо запрограммировать алгоритм, правильно
обрабатывающий любой допустимый набор исходных данных.
Ввод данных выполнен правильно. Однако наша программа не выводит
результатов. Начиная с версии 4.15, в данной ситуации выводится сообщение
на светло-синем фоне: «Запуск с правильным вводом данных: все требуемые
исходные данные введены, результаты не выведены».
Светло-синяя индикация означает, что успешно пройден первый этап решения:
ввод исходных данных. Заметим, что в предыдущих версиях задачника в аналогичной ситуации
выводилось сообщение об ошибке на оранжевом фоне
«Выведены не все результирующие данные. Количество выведенных данных: 0
(из 2)».
Вычисления и вывод полученных данных
Выполним необходимые вычисления и выведем результаты, используя метод put:
[Ruby]
def solve()
task "Begin3"
a = get_f
b = get_f
p = 2 * (a + b)
s = a * b
put P, S
end
[Julia]
function solve()
task("Begin3")
a = get_f()
b = get_f()
p = 2 * (a + b)
s = a * b
put(P, S)
end
Обратите внимание на то, что параметры функций в языке Ruby не требуется заключать
в круглые скобки (хотя это и не запрещается), а в языке Julia скобки после имени вызываемой функции
необходимо указывать всегда, даже если функция не имеет параметров.
При запуске этого варианта программы в информационной панели окна задачника будет выведено сообщение
об ошибке (на красном фоне):
«Error NameError: uninitialized constant P» (для языка Ruby) или
«UndefVarError: P not defined» (для языка Julia). Это же сообщение будет выведен в окне терминала
программ VS Code и RubyMine.
Наша ошибка объясняется тем обстоятельством, что в программах на языках Ruby и Julia учитывается регистр символов,
и поэтому переменные p и P считаются различными (при этом, по правилам языка Ruby, переменные, начинающиеся с заглавной
буквы, считаются константами). Так как ранее в нашей программе константа P не использовалась, она считается
неопределенной, о чем и выводится сообщение. Для исправления программы достаточно изменить
ее последний оператор:
[Ruby]
put p, s
[Julia]
put(p, s)
Исправленная программа не содержит ошибок, препятствующих ее выполнению. После ее запуска
мы можем убедиться, что найденные значения выведены в разделе результирующих данных. Но из-за того,
что вначале мы вывели значение периметра p, а затем значение площади s, решение признано неверным,
а сообщение об ошибке имеет вид «Ошибочное решение».
Подобное сообщение означает, что все исходные данные были
введены, все результирующие данные выведены, но значения полученных результатов не совпадают с контрольными:
Следует обратить внимание на индикаторы, появившиеся в окне задачника
(индикаторы были добавлены в окно задачника в версии 4.11).
В окне с динамической компоновкой для индикаторов отводится
специальная панель, которая располагается под информационной панелью; в качестве индикаторов
используются цветные горизонтальные полосы, а также цветные квадратные маркеры.
Полосы серого цвета показывают, какая часть исходных данных была введена
в ходе выполнения задания и какая часть результатов была выведена.
Полосы и маркеры различных оттенков красного цвета определяют характер обнаруженной ошибки.
В нашем случае индикаторы показывают, что были введены и выведены все требуемые данные.
Обратившись к примеру верного решения,
приведенному в окне задачника, мы видим, что площадь и периметр
найдены верно и нарушен только порядок их вывода. В окне с динамической компоновкой
пример верного решения выводится ниже раздела результатов.
Таким образом, важно не только найти правильные значения результирующих данных, но и вывести их в нужном порядке.
Для того чтобы указать этот порядок, в разделе результатов используется поясняющий текст (см. приведенный выше рисунок окна задачника).
Заметим, что исходные данные тоже важно вводить именно в том порядке, в котором они указаны в окне задачника.
Общее правило здесь следующее: ввод и вывод данных производится по строкам (слева направо),
а строки просматриваются сверху вниз. Иными словами, данные, отображаемые в окне задачника, вводятся и
выводятся в том порядке, в котором читается обычный текст на русском языке.
Правильное решение и его тестирование
Исправим допущенную ошибку:
[Ruby]
put s, p
[Julia]
put(s, p)
После запуска исправленной программы на экране появится окно прогресса тестирования:
Данное окно отображается на экране, если программа успешно обработала хотя бы один
набор исходных данных. Полоса прогресса показывает, сколько тестов было успешно пройдено
к текущему моменту, а текст над полосой дублирует эту информацию и позволяет определить количество тестов,
которое должна успешно пройти программа, чтобы задание считалось выполненным.
Тестирование программы завершается в двух случаях: когда будет успешно пройдено требуемое число
тестов или когда при прохождении очередного теста будет выявлена ошибка.
В нашем случае решение не содержит ошибок, поэтому после прохождения трех успешных тестов
на экране появится окно задачника с сообщением «Задание выполнено!».
Выполнение задания Begin3 завершено:
Возможность автоматического тестирования программы на нескольких
наборах исходных данных была реализована в версии 4.13 задачника. В предыдущих версиях
для тестирования на различных наборах данных программу требовалось запускать несколько раз;
при этом на информационной панели выводилась информация о количестве успешно пройденных тестов.
Возможность подобного «пошагового» тестирования сохранена и в последующих версиях; для этого
надо дополнить имя задания в функции task символом «!» (восклицательный знак).
С помощью модуля PT4Results можно просмотреть информацию о ходе
выполнения задания (начиная с версии 4.11, этот модуль можно вызывать непосредственно из окна задачника;
для этого достаточно нажать клавишу [F2] или щелкнуть мышью на метке с описанием этой клавиши,
размещенной в правом верхнем углу окна задачника):
Begin3 r04/02 14:57 Ознакомительный запуск.
Begin3 r04/02 15:07 Запуск с правильным вводом данных.
Begin3 r04/02 15:09 Error NameError.
Begin3 r04/02 15:12 Ошибочное решение.
Begin3 r04/02 15:15 Задание выполнено!
Буква «r», указанная перед датой, означает, что задание выполнялось на языке Ruby
(для языка Julia используется буква «u»).
[Ruby]
def solve()
task "Begin3"
a, b = get, get
put a * b, 2 * (a + b)
end
[Julia]
function solve()
task("Begin3")
a, b = get(), get()
put(a * b, 2 * (a + b))
end
[Ruby]
a, b = get2
[Julia]
a, b = get2()
[Ruby]
def solve()
task "Begin3"
a, b = get2
(a * b).put
(2 * (a + b)).put
end
|