Редакция для Шифровальщик/расшифровальщик Цезаря
Submitting an official solution before solving the problem yourself is a bannable offence.
1. Идея
Нужно реализовать работу шифра Цезаря в двух режимах:
enc— сдвигать каждую заглавную латинскую букву наkпозиций вперёд;dec— сдвигать каждую заглавную латинскую букву наkпозиций назад.
При этом сдвиг циклический:
- после
ZидётA; - перед
AидётZ.
Все символы, которые не являются заглавными латинскими буквами, менять не нужно.
Задача решается прямой обработкой строки посимвольно.
2. Наблюдения
Алфавит состоит из 26 букв: от
AдоZ.Удобно не работать с буквами напрямую, а перевести букву в номер от
0до25:A->0B->1- ...
Z->25
Тогда:
- в режиме
encновая позиция равна(x + k) % 26; - в режиме
decновая позиция равна(x - k + 26) % 26.
- в режиме
Прибавление
26в расшифровке нужно, чтобы не получить отрицательное число перед взятием остатка.Пробелы и другие символы по условию не изменяются, значит их можно просто сразу переносить в ответ.
3. Алгоритм
- Считать строку
mode— режим работы,encилиdec. - Считать число
k. - Считать строку
s— исходный текст. - Создать строку ответа.
- Для каждого символа
cизs:- если
cнаходится в диапазоне отAдоZ:- найти его номер
x = c - 'A'; - если
mode == "enc", вычислитьx = (x + k) % 26; - иначе вычислить
x = (x - k + 26) % 26; - преобразовать номер обратно в букву и добавить в ответ;
- найти его номер
- иначе добавить символ в ответ без изменений.
- если
- Вывести получившуюся строку.
4. Почему это работает
Рассмотрим любой символ строки.
Случай 1: символ — заглавная латинская буква
Каждой букве сопоставляется число от 0 до 25. Это естественная нумерация букв алфавита.
- В режиме
encнужно сдвинуть букву вперёд наkпозиций. Это ровно означает прибавитьkк её номеру. - Так как алфавит циклический, после
25снова идёт0. Именно это делает операция% 26.
Пример:
Yимеет номер24- при
k = 3получаем(24 + 3) % 26 = 1 - номер
1— этоB
Аналогично в режиме dec нужно сдвинуть букву назад на k позиций, то есть вычесть k. Если результат стал отрицательным, цикл по алфавиту возвращает нас в конец. Формула (x - k + 26) % 26 делает это корректно.
Значит каждая заглавная буква преобразуется ровно так, как требует условие.
Случай 2: символ не является заглавной латинской буквой
По условию такие символы менять не нужно. Алгоритм оставляет их без изменений, значит и здесь всё верно.
Поскольку каждый символ обрабатывается правильно, вся итоговая строка тоже будет правильной.
5. Сложность
Пусть длина строки равна n.
- Время работы:
O(n), потому что каждый символ обрабатывается один раз. - Дополнительная память:
O(n)для хранения результата.
6. Код на C++17
#include <iostream>
#include <string>
using namespace std;
int main() {
string mode;
int k;
string s;
getline(cin, mode);
cin >> k;
cin.ignore();
getline(cin, s);
string result = s;
for (int i = 0; i < (int)s.size(); i++) {
char c = s[i];
if (c >= 'A' && c <= 'Z') {
int x = c - 'A';
if (mode == "enc") {
x = (x + k) % 26;
} else {
x = (x - k + 26) % 26;
}
result[i] = char('A' + x);
} else {
result[i] = c;
}
}
cout << result << "\n";
return 0;
}
7. Код на Python 3
mode = input().strip()
k = int(input())
s = input()
result = []
for c in s:
if 'A' <= c <= 'Z':
x = ord(c) - ord('A')
if mode == 'enc':
x = (x + k) % 26
else:
x = (x - k) % 26
result.append(chr(ord('A') + x))
else:
result.append(c)
print(''.join(result))
Комментарии