I attempted to recreate the Polybius square, also called the Polybius checkerboard, which was used in Ancient Greece for cryptography. Since it is an uncommon cipher, it is nowhere on Code Review.
Although the program technically works, it ended up very messy.
#include <iostream>
#include <algorithm>
#include <vector>
#include <sstream>
#include <iterator>
#include <unordered_map>
std::string getChoice();
std::vector<std::string> getCoords();
int main(){
std::string choice = getChoice();
if(choice == "e"){
std::cout << "Input string: ";
std::string input;
std::getline(std::cin, input);
input.erase(remove_if(input.begin(), input.end(), isspace), input.end());
std::unordered_map<char, unsigned int> alphaToInt = {
{'A', 11},
{'B', 12},
{'C', 13},
{'D', 14},
{'E', 15},
{'F', 21},
{'G', 22},
{'H', 23},
{'I', 24},
{'J', 24}, // same as I
{'K', 25},
{'L', 31},
{'M', 32},
{'N', 33},
{'O', 34},
{'P', 35},
{'Q', 41},
{'R', 42},
{'S', 43},
{'T', 44},
{'U', 45},
{'V', 51},
{'W', 52},
{'X', 53},
{'Y', 54},
{'Z', 55},
};
for(int i = 0; i < input.length(); ++i){
std::cout << alphaToInt[input[i]] << ' ';
}
} else{
std::vector<std::string> coords = getCoords();
std::string output;
const std::string squareIJ[5][5] = {
{"A", "B", "C", "D", "E"},
{"F", "G", "H", "I", "K"},
{"L", "M", "N", "O", "P"},
{"Q", "R", "S", "T", "U"},
{"V", "W", "X", "Y", "Z"},
};
for(int i = 0; i < coords.size(); ++i){
std::string coord = coords[i];
output.append(squareIJ[coord[0] - '1'][coord[1] - '1']);
}
std::cout << output;
}
std::cout << '\n';
return 0;
}
std::string getChoice(){
std::string choice;
do{
std::cout << "Encrypt or decrypt [e/d] = ";
std::getline(std::cin, choice);
if(choice == "E") choice = "e";
std::transform(choice.begin(), choice.end(), choice.begin(), ::tolower);
} while(choice != "e" && choice != "d");
return choice;
}
std::vector<std::string> getCoords(){
std::cout << "Coordinates (separate with spaces): ";
std::string strCoords;
std::getline(std::cin, strCoords);
std::stringstream streamCoords(strCoords);
std::istream_iterator<std::string> begin(streamCoords);
std::istream_iterator<std::string> end;
std::vector<std::string> coords(begin, end);
return coords;
}
The Polybius square is a simple way to assign characters numbers, and then "encrypt" and "decrypt" based off of those numbers. As shown in the unordered map and char
array, the numbers correspond to the row and column on a 5x5 square:
The getChoice()
function simply gets the e
or d
character to choose encryption or decryption.
The getCoords()
function gets a string, and then tokenizes the string into a vector of strings, each corresponding to the coordinates of a character.
Example of "encryption":
Encrypt or decrypt [e/d] = e
Input string: BAT
12 11 44
Example of "decryption":
Encrypt or decrypt [e/d] = d
Coordinates (separate with spaces): 12 11 44
BAT
This code, in my opinion, is quite messy. How can I improve it?