#include <algorithm>
#include <cctype>
#include <string>
#include <iostream>
template <typename InputIterator, typename OutputIterator>
OutputIterator caesar_cipher(InputIterator src_begin, InputIterator src_end, OutputIterator dest_begin, int shift)
{
const std::string ab("abcdefghijklmnopqrstuvwxyz"); // AlphaBet
std::string rot_ab(ab); // ROTated AlphaBet
shift %= static_cast<int> (ab.length()); // bring the shift within the length of the alphabet
if (shift < 0)
std::rotate(rot_ab.rbegin(), rot_ab.rbegin() - shift, rot_ab.rend());
else
std::rotate(rot_ab.begin(), rot_ab.begin() + shift, rot_ab.end());
auto rotator = [ab, rot_ab](char c) -> char {
if (std::isalpha(c))
{
if (std::isupper(c))
return std::toupper(rot_ab.at(ab.find(std::tolower(c))));
return rot_ab.at(ab.find(c));
}
return c;
};
return std::transform(src_begin, src_end, dest_begin, rotator);
}
int main() {
std::string s = "Wkh Txlfn Eurzq Ira Mxpsv Ryhu Wkh Odcb Grj";
caesar_cipher(s.begin(), s.end(), s.begin(), -3);
std::cout << s << std::endl;
}
I2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPGNjdHlwZT4KI2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPGlvc3RyZWFtPgoKdGVtcGxhdGUgPHR5cGVuYW1lIElucHV0SXRlcmF0b3IsIHR5cGVuYW1lIE91dHB1dEl0ZXJhdG9yPgpPdXRwdXRJdGVyYXRvciBjYWVzYXJfY2lwaGVyKElucHV0SXRlcmF0b3Igc3JjX2JlZ2luLCBJbnB1dEl0ZXJhdG9yIHNyY19lbmQsIE91dHB1dEl0ZXJhdG9yIGRlc3RfYmVnaW4sIGludCBzaGlmdCkKewogICAgY29uc3Qgc3RkOjpzdHJpbmcgYWIoImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6Iik7IC8vIEFscGhhQmV0CiAgICBzdGQ6OnN0cmluZyByb3RfYWIoYWIpOyAvLyBST1RhdGVkIEFscGhhQmV0CgogICAgc2hpZnQgJT0gc3RhdGljX2Nhc3Q8aW50PiAoYWIubGVuZ3RoKCkpOyAvLyBicmluZyB0aGUgc2hpZnQgd2l0aGluIHRoZSBsZW5ndGggb2YgdGhlIGFscGhhYmV0CgogICAgaWYgKHNoaWZ0IDwgMCkKICAgICAgICBzdGQ6OnJvdGF0ZShyb3RfYWIucmJlZ2luKCksIHJvdF9hYi5yYmVnaW4oKSAtIHNoaWZ0LCByb3RfYWIucmVuZCgpKTsKICAgIGVsc2UKICAgICAgICBzdGQ6OnJvdGF0ZShyb3RfYWIuYmVnaW4oKSwgcm90X2FiLmJlZ2luKCkgKyBzaGlmdCwgcm90X2FiLmVuZCgpKTsKICAgICAgICAKICAgIGF1dG8gcm90YXRvciA9IFthYiwgcm90X2FiXShjaGFyIGMpIC0+IGNoYXIgewogICAgICAgIGlmIChzdGQ6OmlzYWxwaGEoYykpCiAgICAgICAgewogICAgICAgICAgICBpZiAoc3RkOjppc3VwcGVyKGMpKQogICAgICAgICAgICAgICAgcmV0dXJuIHN0ZDo6dG91cHBlcihyb3RfYWIuYXQoYWIuZmluZChzdGQ6OnRvbG93ZXIoYykpKSk7CgogICAgICAgICAgICByZXR1cm4gcm90X2FiLmF0KGFiLmZpbmQoYykpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIGM7CiAgICB9OwoKICAgIHJldHVybiBzdGQ6OnRyYW5zZm9ybShzcmNfYmVnaW4sIHNyY19lbmQsIGRlc3RfYmVnaW4sIHJvdGF0b3IpOwp9CgppbnQgbWFpbigpIHsKICAgIHN0ZDo6c3RyaW5nIHMgPSAiV2toIFR4bGZuIEV1cnpxIElyYSBNeHBzdiBSeWh1IFdraCBPZGNiIEdyaiI7CgogICAgY2Flc2FyX2NpcGhlcihzLmJlZ2luKCksIHMuZW5kKCksIHMuYmVnaW4oKSwgLTMpOwogICAgc3RkOjpjb3V0IDw8IHMgPDwgc3RkOjplbmRsOwp9