Редакция для Шифровальщик/расшифровальщик Цезаря


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.

1. Идея

Нужно реализовать работу шифра Цезаря в двух режимах:

  • enc — сдвигать каждую заглавную латинскую букву на k позиций вперёд;
  • dec — сдвигать каждую заглавную латинскую букву на k позиций назад.

При этом сдвиг циклический:

  • после Z идёт A;
  • перед A идёт Z.

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

Задача решается прямой обработкой строки посимвольно.

2. Наблюдения

  1. Алфавит состоит из 26 букв: от A до Z.

  2. Удобно не работать с буквами напрямую, а перевести букву в номер от 0 до 25:

    • A -> 0
    • B -> 1
    • ...
    • Z -> 25
  3. Тогда:

    • в режиме enc новая позиция равна (x + k) % 26;
    • в режиме dec новая позиция равна (x - k + 26) % 26.
  4. Прибавление 26 в расшифровке нужно, чтобы не получить отрицательное число перед взятием остатка.

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

3. Алгоритм

  1. Считать строку mode — режим работы, enc или dec.
  2. Считать число k.
  3. Считать строку s — исходный текст.
  4. Создать строку ответа.
  5. Для каждого символа c из s:
    • если c находится в диапазоне от A до Z:
      • найти его номер x = c - 'A';
      • если mode == "enc", вычислить x = (x + k) % 26;
      • иначе вычислить x = (x - k + 26) % 26;
      • преобразовать номер обратно в букву и добавить в ответ;
    • иначе добавить символ в ответ без изменений.
  6. Вывести получившуюся строку.

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))

Комментарии

Еще нет ни одного комментария.