Skip to content
214 changes: 73 additions & 141 deletions ciphers/a1z26_cipher.cpp
Original file line number Diff line number Diff line change
@@ -1,162 +1,94 @@
/**
* @file
* @brief Implementation of the [A1Z26
* cipher](https://www.dcode.fr/letter-number-cipher)
* @details The A1Z26 cipher is a simple substiution cipher where each letter is
* replaced by the number of the order they're in. For example, A corresponds to
* 1, B = 2, C = 3, etc.
*
* @author [Focusucof](https://github.com/Focusucof)
* @file a1z26_cipher.cpp
* @brief A1Z26 字母数字密码(A=1, B=2 ... Z=26)
*/

#include <algorithm> /// for std::transform and std::replace
#include <cassert> /// for assert
#include <cstdint> /// for uint8_t
#include <iostream> /// for IO operations
#include <map> /// for std::map
#include <sstream> /// for std::stringstream
#include <string> /// for std::string
#include <vector> /// for std::vector
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
#include <cassert>
#include <cctype>

/**
* @namespace ciphers
* @brief Algorithms for encryption and decryption
*/
namespace ciphers {
/**
* @namespace a1z26
* @brief Functions for [A1Z26](https://www.dcode.fr/letter-number-cipher)
* encryption and decryption implementation
*/
namespace a1z26 {

std::map<uint8_t, char> a1z26_decrypt_map = {
{1, 'a'}, {2, 'b'}, {3, 'c'}, {4, 'd'}, {5, 'e'}, {6, 'f'}, {7, 'g'},
{8, 'h'}, {9, 'i'}, {10, 'j'}, {11, 'k'}, {12, 'l'}, {13, 'm'}, {14, 'n'},
{15, 'o'}, {16, 'p'}, {17, 'q'}, {18, 'r'}, {19, 's'}, {20, 't'}, {21, 'u'},
{22, 'v'}, {23, 'w'}, {24, 'x'}, {25, 'y'}, {26, 'z'},
};

std::map<char, uint8_t> a1z26_encrypt_map = {
{'a', 1}, {'b', 2}, {'c', 3}, {'d', 4}, {'e', 5}, {'f', 6}, {'g', 7},
{'h', 8}, {'i', 9}, {'j', 10}, {'k', 11}, {'l', 12}, {'m', 13}, {'n', 14},
{'o', 15}, {'p', 16}, {'q', 17}, {'r', 18}, {'s', 19}, {'t', 20}, {'u', 21},
{'v', 22}, {'w', 23}, {'x', 24}, {'y', 25}, {'z', 26}};

/**
* @brief a1z26 encryption implementation
* @param text is the plaintext input
* @returns encoded string with dashes to seperate letters
*/
std::string encrypt(std::string text) {
std::string result;
std::transform(text.begin(), text.end(), text.begin(),
::tolower); // convert string to lowercase
std::replace(text.begin(), text.end(), ':', ' ');
for (char letter : text) {
if (letter != ' ') {
result += std::to_string(
a1z26_encrypt_map[letter]); // convert int to string and append
// to result
result += "-"; // space out each set of numbers with spaces
} else {
result.pop_back();
result += ' ';
// 加密:字母 → 数字(用 - 分隔)
std::string encrypt(const std::string& text) {
std::string res;
for (char c : text) {
if (c == ' ') {
res += ' ';
continue;
}
int num = tolower(c) - 'a' + 1;
res += std::to_string(num) + "-";
}
result.pop_back(); // remove leading dash
return result;
if (!res.empty() && res.back() == '-')
res.pop_back();

// 把 "- " 换成 " "
size_t pos;
while ((pos = res.find("- ")) != std::string::npos)
res.replace(pos, 2, " ");
return res;
}

/**
* @brief a1z26 decryption implementation
* @param text is the encrypted text input
* @param bReturnUppercase is if the decoded string should be in uppercase or
* not
* @returns the decrypted string in all uppercase or all lowercase
*/
std::string decrypt(const std::string& text, bool bReturnUppercase = false) {
std::string result;

// split words seperated by spaces into a vector array
std::vector<std::string> word_array;
std::stringstream sstream(text);
std::string word;
while (sstream >> word) {
word_array.push_back(word);
}

for (auto& i : word_array) {
std::replace(i.begin(), i.end(), '-', ' ');
std::vector<std::string> text_array;

std::stringstream ss(i);
std::string res_text;
while (ss >> res_text) {
text_array.push_back(res_text);
// 解密:数字 → 字母
std::string decrypt(const std::string& text, bool uppercase = false) {
std::string res;
std::stringstream ss(text);
std::string part;

while (std::getline(ss, part, ' ')) {
std::stringstream ss2(part);
std::string num_str;
while (std::getline(ss2, num_str, '-')) {
int num = std::stoi(num_str);
char c = 'a' + num - 1;
res += c;
}

for (auto& i : text_array) {
result += a1z26_decrypt_map[stoi(i)];
}

result += ' ';
res += ' ';
}
result.pop_back(); // remove any leading whitespace
if (!res.empty())
res.pop_back();

if (bReturnUppercase) {
std::transform(result.begin(), result.end(), result.begin(), ::toupper);
}
return result;
if (uppercase)
std::transform(res.begin(), res.end(), res.begin(), ::toupper);
return res;
}

} // namespace a1z26
} // namespace ciphers

/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
// 1st test
std::string input = "Hello World";
std::string expected = "8-5-12-12-15 23-15-18-12-4";
std::string output = ciphers::a1z26::encrypt(input);

std::cout << "Input: " << input << std::endl;
std::cout << "Expected: " << expected << std::endl;
std::cout << "Output: " << output << std::endl;
assert(output == expected);
std::cout << "TEST PASSED";

// 2nd test
input = "12-15-23-5-18-3-1-19-5";
expected = "lowercase";
output = ciphers::a1z26::decrypt(input);

std::cout << "Input: " << input << std::endl;
std::cout << "Expected: " << expected << std::endl;
std::cout << "Output: " << output << std::endl;
assert(output == expected);
std::cout << "TEST PASSED";

// 3rd test
input = "21-16-16-5-18-3-1-19-5";
expected = "UPPERCASE";
output = ciphers::a1z26::decrypt(input, true);

std::cout << "Input: " << input << std::endl;
std::cout << "Expected: " << expected << std::endl;
std::cout << "Output: " << output << std::endl;
assert(output == expected);
std::cout << "TEST PASSED";
} // namespace a1z26
} // namespace ciphers

// 测试
void test() {
// 测试 1:加密
std::string text = "Hello World";
std::string expect_enc = "8-5-12-12-15 23-15-18-12-4";
std::string enc = ciphers::a1z26::encrypt(text);
assert(enc == expect_enc);

// 测试 2:解密小写
std::string enc_text = "12-15-23-5-18-3-1-19-5";
std::string expect_dec = "lowercase";
std::string dec = ciphers::a1z26::decrypt(enc_text);
assert(dec == expect_dec);

// 测试 3:解密大写
std::string enc2 = "21-16-16-5-18-3-1-19-5";
std::string expect_upper = "UPPERCASE";
std::string dec_upper = ciphers::a1z26::decrypt(enc2, true);
assert(dec_upper == expect_upper);

std::cout << "✅ 所有 A1Z26 测试通过!\n";
std::cout << "原文: " << text << "\n";
std::cout << "加密: " << enc << "\n";
std::cout << "解密: " << ciphers::a1z26::decrypt(enc) << "\n";
}

/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
test();
return 0;
}
106 changes: 40 additions & 66 deletions ciphers/atbash_cipher.cpp
Original file line number Diff line number Diff line change
@@ -1,84 +1,58 @@
/**
* @file
* @brief [Atbash Cipher](https://en.wikipedia.org/wiki/Atbash) implementation
* @details The Atbash cipher is a subsitution cipher where the letters of the
* alphabet are in reverse. For example, A is replaced with Z, B is replaced
* with Y, etc.
*
* ### Algorithm
* The algorithm takes a string, and looks up the corresponding reversed letter
* for each letter in the word and replaces it. Spaces are ignored and case is
* preserved.
*
* @author [Focusucof](https://github.com/Focusucof)
* @file atbash_cipher.cpp
* @brief 阿特巴什密码(反转字母表)
*/
#include <cassert> /// for assert
#include <iostream> /// for IO operations
#include <map> /// for std::map
#include <string> /// for std::string

/** \namespace ciphers
* \brief Algorithms for encryption and decryption
*/
#include <iostream>
#include <string>
#include <cassert>
#include <cctype>

namespace ciphers {
/** \namespace atbash
* \brief Functions for the [Atbash
* Cipher](https://en.wikipedia.org/wiki/Atbash) implementation
*/
namespace atbash {
std::map<char, char> atbash_cipher_map = {
{'a', 'z'}, {'b', 'y'}, {'c', 'x'}, {'d', 'w'}, {'e', 'v'}, {'f', 'u'},
{'g', 't'}, {'h', 's'}, {'i', 'r'}, {'j', 'q'}, {'k', 'p'}, {'l', 'o'},
{'m', 'n'}, {'n', 'm'}, {'o', 'l'}, {'p', 'k'}, {'q', 'j'}, {'r', 'i'},
{'s', 'h'}, {'t', 'g'}, {'u', 'f'}, {'v', 'e'}, {'w', 'd'}, {'x', 'c'},
{'y', 'b'}, {'z', 'a'}, {'A', 'Z'}, {'B', 'Y'}, {'C', 'X'}, {'D', 'W'},
{'E', 'V'}, {'F', 'U'}, {'G', 'T'}, {'H', 'S'}, {'I', 'R'}, {'J', 'Q'},
{'K', 'P'}, {'L', 'O'}, {'M', 'N'}, {'N', 'M'}, {'O', 'L'}, {'P', 'K'},
{'Q', 'J'}, {'R', 'I'}, {'S', 'H'}, {'T', 'G'}, {'U', 'F'}, {'V', 'E'},
{'W', 'D'}, {'X', 'C'}, {'Y', 'B'}, {'Z', 'A'}, {' ', ' '}

};

/**
* @brief atbash cipher encryption and decryption
* @param text Plaintext to be encrypted
* @returns encoded or decoded string
*/
std::string atbash_cipher(const std::string& text) {
// 加密 = 解密(对称)
std::string atbash(const std::string& text) {
std::string result;
for (char letter : text) {
result += atbash_cipher_map[letter];
for (unsigned char c : text) {
if (std::isalpha(c)) {
if (std::isupper(c)) {
// 大写:A ↔ Z,B ↔ Y ...
result += 'Z' - (c - 'A');
} else {
// 小写:a ↔ z,b ↔ y ...
result += 'z' - (c - 'a');
}
} else {
// 非字母直接保留
result += c;
}
}
return result;
}

} // namespace atbash
} // namespace ciphers
} // namespace atbash
} // namespace ciphers

/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
// 1st test
// 测试
void test() {
std::string text = "Hello World";
std::string expected = "Svool Dliow";
std::string encrypted_text = ciphers::atbash::atbash_cipher(text);
std::string decrypted_text = ciphers::atbash::atbash_cipher(encrypted_text);
assert(expected == encrypted_text);
assert(text == decrypted_text);
std::cout << "Original text: " << text << std::endl;
std::cout << ", Expected text: " << expected << std::endl;
std::cout << ", Encrypted text: " << encrypted_text << std::endl;
std::cout << ", Decrypted text: " << decrypted_text << std::endl;
std::cout << "\nAll tests have successfully passed!\n";
std::string expect = "Svool Dliow";

std::string enc = ciphers::atbash::atbash(text);
std::string dec = ciphers::atbash::atbash(enc);

std::cout << "原始文本: " << text << '\n';
std::cout << "加密结果: " << enc << '\n';
std::cout << "解密结果: " << dec << '\n';

assert(enc == expect);
assert(dec == text);

std::cout << "\n✅ Atbash 密码测试通过!\n";
}

/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
test();
return 0;
}
Loading