/*
The purpose of this program is to emulate the workings of a simple substitution
cypher. The cypher does not distinguish between "encrypted" or "decrypted"
states; rather it simply translates between the characters contained in the
cypher and allows plain passthrough of the remaining characters.
Here's an example of a valid, albeit weak, cypher:
TENIS
-----
POLAR
This cypher is valid because it contains two rows that are of the same length
and contain distinct characters - no two equal characters appear in any row.
The cyphers may contain any character (alphanumeric, non-alphanumeric,
accented, extended Unicode...) depending on the complexity of the cypher you
wish to have provided that character collisions do not happen.
*/
#include <iostream>
#include <string>
#include <vector>
typedef std::vector<char> cypherrow;
bool validate_cypher(cypherrow row1, cypherrow row2)
{
bool statuscode = true;
for (auto letter1 : row1) {
for (auto letter2 : row2) {
if (letter1 == letter2) {
std::cout << "Warning: cypher collision detected at '" << letter1 << "'!\n";
statuscode = false;
}
}
}
return statuscode;
}
// Begin translation. Note that it's symmetrical, as in we don't exactly have
// a "state" saying encypted or decrypted. The cypher takes a letter, sees if
// it has it available and rotates it. That's it.
std::string translate(std::string input, cypherrow r1, cypherrow r2) {
std::string output = ""; // this will become the final string.
bool match = false;
int row(0);
int index(0);
for (auto letter : input) {
match = false;
for (auto letter1 = r1.begin();
letter1 != r1.end(); ++letter1) {
if (letter == *letter1) {
// we got a match!
match = true;
row = 1;
index = letter1 - r1.begin();
break;
}
}
if (match == false) {
for (auto letter2 = r2.begin();
letter2 != r2.end(); ++letter2) {
if (letter == *letter2) {
// we got a match!
match = true;
row = 2;
index = letter2 - r2.begin();
break;
}
}
}
// uncomment the following block for debugging!
/*
std::cout << "Now manipulating letter " << letter << ", match is "
<< match << " row is " << row << " index is " << index << std::endl;
*/
if (match) {
std::string newletter;
// get the letter in the opposite row at the same index:
if (row == 1) {
newletter = r2.at(index);
}
else if (row == 2) {
newletter = r1.at(index);
}
// compose the new string by appending it to the string:
output.append(newletter);
}
else {
// push the character unchanged:
std::string unchanged;
unchanged = std::string(1, (char)letter);
output.append(unchanged);
}
}
return output;
}
int main(int argc, char * argv[])
{
cypherrow row1 {'p','l','e','a','i','z','o','m'};
cypherrow row2 {'b','n','u','f','c','s','y','r'};
if (validate_cypher(row1, row2)) {
std::cout << "Cypher is good.\n";
}
else {
std::cout << "You have a corrupted cypher.\n";
std::cout << "Please fix it before running this program.\n";
return 1;
}
std::string samplestring;
std::cout << "Enter the text to be translated:\n>_ ";
std::getline(std::cin, samplestring);
std::cout << translate(samplestring, row1, row2) << std::endl;
return 0;
}