Programming Taskbook


E-mail:

Пароль:

Регистрация пользователя   Восстановление пароля

 

ЮФУ SMBU

Электронный задачник по программированию

©  М. Э. Абрамян (Южный федеральный университет, Университет МГУ-ППИ в Шэньчжэне), 1998–2024

 

Решения | Ruby и Julia | Обработка строк

PrevNext


Выполнение задания на обработку строк: String9

Особенности выполнения заданий на обработку символов и строк рассмотрим на примере задания String9.

String9°. Дано четное число N (> 0) и символы C1 и C2. Вывести строку длины N, которая состоит из чередующихся символов C1 и C2, начиная с C1.

Создание программы-заготовки и знакомство с заданием

Программу-заготовку для решения задания String9 можно создать с помощью модуля PT4Load. В созданный проект будет входить файл String9.rb (Ruby) или String9.jl (Julia). Приведем текст функции solve из данного файла (именно в эту функцию требуется ввести решение задачи):

[Ruby]

def solve()
    task "String9"

end

[Julia]

function solve()
    task("String9")

end

После запуска программы на экране появится окно задачника. На рисунке приведены два варианта представления окна — в режиме с динамической и с фиксированной компоновкой:


Символьные и строковые данные в окне задачника для языка Ruby заключаются в двойные кавычки; это позволяет отличить числовые данные (например, 2) от символьных и строковых данных, содержащих цифры (например, символа "2"). Кроме того, кавычки дают возможность увидеть пробелы, находящиеся в начале или в конце строк. В языке Julia различаются символьные и строковые данные, поэтому в окне задачника символьные данные будут звключаться в одинарные кавычки, а строковые — в двойные, что соответствует правилам этого языка.

Ввод исходных данных

Добавим в программу фрагмент, обеспечивающий ввод исходных данных. Для ввода данных целого типа можно использовать функцию get_i, символьные данные в языке Ruby можно вводить функцией get_s, а в языке Julia — функцией get_c:

[Ruby]

def solve()
    task "String9"
    a = get_s
    b = get_s
    n = get_i

end

[Julia]

function solve()
    task("String9")
    a = get_c()
    b = get_c()
    n = get_i()

end

Мы намеренно ввели данные не в том порядке, в котором они указаны в окне задачника.

Запуск нового варианта программы уже не будет считаться ознакомительным, поскольку в программе выполняется ввод исходных данных. Так как порядок ввода исходных данных является ошибочным, этот вариант решения будет признан неверным и приведет к сообщению «Неверно указан тип при вводе исходных данных. Для ввода 1-го элемента (целого типа) использована переменная строкового типа» (для языка Julia в сообщении вместо слова «строкового» будет использовано слово «символьного»).

Напомним правило, определяющее порядок ввода и вывода данных для задачника Programming Taskbook: ввод и вывод данных производится по строкам (слева направо), а строки просматриваются сверху вниз.

Примечание 1. Если бы для ввода исходных данных использовалась «универсальная» функция get, то задачник не обнаружил бы ошибок ввода, однако в результате в переменную a было бы записано целое число, а в переменные b и n — символы. Таким образом, содержимое переменных не соответствовало бы их назначению, что в дальнейшем обязательно привело бы к неправильной работе алгоритма, использующего эти переменные. Приведенный пример наглядно показывает преимущества использования специализированных функций ввода, позволяющих сразу распознать типичные ошибки при чтении исходных данных.

Исправим программу, изменив в ней порядок ввода:

[Ruby]

def solve()
    task "String9"
    n = get_i
    a = get_s
    b = get_s

end

[Julia]

function solve()
    task("String9")
    n = get_i()
    a = get_c()
    b = get_c()

end

Теперь исходные данные вводятся правильно. Первый этап решения задачи пройден.

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

[Ruby]

def solve()
    task "String9"
    n, a, b = get3

end

[Julia]

function solve()
    task("String9")
    n, a, b = get3()

end

Формирование требуемой строки и ее вывод

Для формирования нужной строки воспользуемся операцией сцепления строк (в языке Ruby она обозначается символом сложения +, а в языке Julia — символом умножения *); для вывода полученной строки используем функцию put:

[Ruby]

def solve()
    task "String9"
    n, a, b = get3
    s = ""
    n.times {s += a + b}
    put s
end

[Julia]

function solve()
    task("String9")
    n, a, b = get3()
    s = ""
    for i in 1:n
        s *= a * b
    end
    put(s)
end

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

"a1a1a1a1a1*

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

Примечание. Красная звездочка может появиться и при выводе ошибочных числовых данных. Например, если ожидается целое число в диапазоне от 1 до 99, а получено число 10000, то на экран будет выведена только первая цифра этого числа, за которой будет указана красная звездочка: 1*.

Правильное решение, его тестирование и просмотр результатов

Ошибка в предыдущей программе возникла из-за неверного указания количества итераций цикла. Действительно, на каждой итерации к строке добавляется по два символа, поэтому после n итераций строка будет содержать 2n символов (а не n, как требуется в задании).

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

[Ruby]

    (n / 2).times {s += a + b}

[Julia]

    for i in 1:n ÷ 2

В варианте для языка Ruby мы использовали операцию «/», поскольку в языке Ruby (как и во многих других языках программирования) эта операция, при наличии обоих операндов целого типа, означает целочисленное деление. В языке Julia для операции деления нацело предусмотрен особый символ ÷, отсутствующий на клавиатуре. Для его ввода в программу надо набрать текст \div и сразу после этого нажать клавишу Tab. Заметим, что текст \div соответствует символу ÷ в системе LaTeX, предназначенной для подготовки математических текстов. Аналогичными действиями в редакторе VS Code можно вводить в программу на языке Julia и другие специальные символы.

После запуска исправленной программы и успешного прохождения 5 тестов мы получим сообщение «Задание выполнено!». Нажав клавишу [F2], мы можем вывести на экран окно результатов, в котором будут перечислены все наши попытки решения задачи (буква «r», которая указывается перед датой, означает, что при выполнении задания использовался язык Ruby; для языка Julia предусмотрена буква «u»):

String9     r06/09 15:46 Ознакомительный запуск.
String9     r06/09 15:50 Неверно указан тип при вводе исходных данных.
String9     r06/09 15:55 Запуск с правильным вводом данных.
String9     r06/09 16:00 Ошибочное решение.
String9     r06/09 16:05 Задание выполнено!

Примечание.При решении задачи можно обойтись без цикла, если воспользоваться специальной возможностью языков Ruby и Julia: операцией сцепления n копий строки s. Для языка Ruby эта операция обозначается символом умножения *, а для языка Julia — символом возведения в степень ^; в обоих языках эта операция должна применяться к строке s и целому числу n в указанном порядке. Таким образом, после ввода исходных данных в нашей программе останется лишь применить эту операцию:

[Ruby]

def solve()
    task "String9"
    n, a, b = get3
    s = (a + b) * (n / 2)
    put s

[Julia]

function solve()
    task("String9")
    n, a, b = get3()
    s = (a * b) ^ (n ÷ 2)
    put(s)
end

Полученное решение можно еще более сократить, если заметить, что значения переменных a и b используются только в одном операторе, и заменить обращения к ним на вызовы функции get (для переменной n такую замену выполнить нельзя, так как число n должно быть введено перед вводом символов a и b). Кроме того, в языке Ruby для вывода можно использовать вариант метода put без параметров, применив его непосредственно к полученной строке. В результате решение будет содержать единственную вспомогательную переменную n и сократится до двух строк (не считая оператора вызова функции task):

[Ruby]

def solve()
    task "String9"
    n = get / 2
    ((get + get) * n).put

[Julia]

function solve()
    task("String9")
    n = get() ÷ 2
    put((get() * get()) ^ n)
end

PrevNext

 

Рейтинг@Mail.ru

Разработка сайта:
М. Э. Абрамян, В. Н. Брагилевский

Последнее обновление:
01.01.2024