Skip to content

Instantly share code, notes, and snippets.

@alzobnin
Created January 28, 2021 13:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alzobnin/8ffba6c7d9d27b17ab97a6019a86a145 to your computer and use it in GitHub Desktop.
Save alzobnin/8ffba6c7d9d27b17ab97a6019a86a145 to your computer and use it in GitHub Desktop.

Разбор задачи "Шифр Цезаря"

Условие

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

Если мы будем зашифровывать слово kenig используя сдвиг размером 13, то получим xravt.

Ваша задача состоит в том, что бы расшифровать строку. Вам дана зашифрованная строка, состоящая не более чем из 1000 строчных или заглавных букв латинского алфавита. Далее записан размер сдвига k, с помощью которого было зашифровано сообщение (0<=k<=10^9).

Выведете исходную строку.

Примеры ввода и вывода:

xravt 13 => kenig.

furg 3 => crod.

ZaQzJzCzAqZ 51 => AbRaKaDaBrA.

Решение

Во-первых, заметим, что в латинском алфавите 26 букв. Далее, вместо сдвига k можно рассматривать его остаток от деления на 26 (так как если k >= 26, то всё равно всё будет сдвигаться по циклу). Из второго примера следует, что k обозначает сдвиг вправо. Поэтому для расшифровки нам надо будет сдвигать буквы влево.

Отдельно надо разобраться со строчными и заглавными буквами: при сдвиге строчных должны получаться строчные, а при сдвиге заглавных - заглавные. Нам достаточно знать, что в таблице ASCII и строчные и заглавные буквы идут подряд по алфавиту.

#include <iostream>
#include <string>

using namespace std;

int main() {
    const int alphabet_size = 26;

    string word;
    cin >> word;

    unsigned int shift;
    cin >> shift;
    shift %= alphabet_size;

    for (size_t i = 0; i != word.size(); ++i) {
        bool upper = isupper(word[i]);
        word[i] = word[i] - shift;
        if (upper) {
            if (word[i] < 'A') {
                word[i] += alphabet_size;
            }
        } else {
            if (word[i] < 'a') {
                word[i] += alphabet_size;
            }
        }
    }

    cout << word << "\n";
}

Вместо вложенных if можно было бы использовать формулу для индексов с остатками от деления на alphabet_size.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment