Skip to content

Instantly share code, notes, and snippets.

@AliBasicCoder
Created March 14, 2024 18:11
Show Gist options
  • Select an option

  • Save AliBasicCoder/9bfd5eb03738580988cca8cb68faa9f1 to your computer and use it in GitHub Desktop.

Select an option

Save AliBasicCoder/9bfd5eb03738580988cca8cb68faa9f1 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <string>
using namespace std;
int getValidKey() {
// print message to user
cout << "please enter your key: ";
// a variable to store the result
int result;
// keep asking user until he gives valid input
while (true) {
// string to store user input
string text;
// clear any errors in cin
cin.clear();
// get user input and store it in text
getline(cin, text);
try {
// convert text to integer, and store it in result
result = stoi(text);
} catch (...) {
// if the text is not an inger ask the user for input again
cout << "Invalid input! please try again: ";
continue;
}
// if the input is less that or equal to 0, re-ask the user for input
if (result <= 0) {
cout << "Value must be bigger than 0! please try again: ";
continue;
}
// if this line is reached the user entered a valid input
// so break the loop (stop asking for input)
break;
}
// return the result
return result;
}
string getValidMessage(int key) {
// get message from user
cout << "please enter your message: ";
while (true) {
string user_message;
cin.clear();
getline(cin, user_message);
if (user_message.length() < key) {
cout << "message is too short! please enter another message: ";
continue;
}
return user_message;
}
}
void routeCipher() {
// get key from user
int key = getValidKey();
// get message from user
string user_message = getValidMessage(key);
// a variable to store the user's message removing non-alphabetic characteristic
// and making all characters capital
string message;
// loop through the user's message
for (int i = 0; i < user_message.length(); i++) {
char c = user_message[i];
// if the character is a capital letter add it to message
if (c >= 65 && c <= 90) {
message.push_back(c);
// if the char is a small letter make it capital and add it
} else if (c >= 97 && c <= 122) {
// ascii code for capital A is 65 and for B is 66 and so on
// until Z is 90
// and the code for small A is 97 for B is 98 and so until Z is 122
// so if we subtract 32 (= 97-65) from the small characters we will convert them into
// capital letters
message.push_back(char((int) c - 32));
}
}
// get length of message
int len = (int) message.length();
// if the length of the message is divisible by the key
// we don't need to add any X's
if (len % key != 0) {
// if we 21 characters and the key is 5
// we need to add 4 Xs which is the
// key - (remainder of len / key)
for (int i = 0; i < key - (len % key); i++) {
message.push_back('X');
}
// re-write len because it changed
len = (int) message.length();
}
// in the following code, we will build a spiral
// that starts from the top right of the matrix
// goes down until the bottom of it, then goes left
// until the far right of it then goes up
// until the top of the matrix then goes right and so on...
// the matrix start counting row and cols from zero
// an int storing the current direction of the spiral
// bottom = 0, top = 1, left = 2, right = 3
int dir = 0;
// current row of character we're printing
int row = 0;
// current col (in the start it's the last col)
int col = key - 1;
// bottom of matrix (in the start it's last row)
int maxBottom = (len / key) - 1;
int maxTop = 0;
int maxLeft = 0;
// the right edge of the spiral.
// in the start it's the col before the last
// because we start at the last
// making this key - 1, we make the spiral visit the last col twice
int maxRight = key - 2;
// print the current character or not?
bool print = true;
for (int i = 0; i < len; i++) {
char c = message[row * key + col];
if (print) cout << c;
else print = true;
// if we are going down...
if (dir == 0) {
// if the current row is the bottom row
if (row == maxBottom) {
// go to the left
dir = 2;
// make the bottom row the one before it
// this is to prevent the spiral from going
// to the current row twice
maxBottom--;
// in order to know where the next character is
// we need to go through the current char again
// but with a different direction, because the
// next character might not be in the left (if the current character
// is already on the far left)
i--;
print = false;
// otherwise increment the current row (go to the next one)
} else row++;
}
else if (dir == 2) {
if (col == maxLeft) {
dir = 1;
maxLeft++;
i--;
print = false;
} else col--;
}
else if (dir == 1) {
if (row == maxTop) {
dir = 3;
maxTop++;
i--;
print = false;
} else row--;
}
else {
if (col == maxRight) {
dir = 0;
maxRight--;
i--;
print = false;
} else col++;
}
}
}
string getValidCipheredMessage(int key) {
cout << "please enter your ciphered message: ";
while (true) {
string user_message;
cin.clear();
getline(cin, user_message);
string message;
for (int i = 0; i < user_message.length(); i++) {
char c = user_message[i];
if (c >= 65 && c <= 90) {
message.push_back(c);
} else if (c >= 97 && c <= 122) {
message.push_back(char((int) c - 32));
}
}
int len = (int) message.length();
if (len % key != 0) {
cout << "Invalid Message (the message length must be divisible by key)! re-enter your message: ";
continue;
}
return message;
}
}
void routeDecipher() {
int key = getValidKey();
string message = getValidCipheredMessage(key);
int len = (int) message.length();
string result;
// make the result the same length as message
// this is because characters are NOT going to be
// writen in it in order
result.resize(len);
// to decipher a message you need to create a matrix
// and write characters in it in the same spiral used to cipher it (starting
// from top right going clock-wise)
// the following is identical to the code above...
int dir = 0;
int row = 0;
int col = key - 1;
int maxBottom = (len / key) - 1;
int maxTop = 0;
int maxLeft = 0;
int maxRight = key - 2;
for (int i = 0; i < len; i++) {
// ...expect instead of printing, we write the characters
// in the correct position
result[row * key + col] = message[i];
if (dir == 0) {
if (row == maxBottom) {
dir = 2;
maxBottom--;
i--;
} else row++;
}
else if (dir == 2) {
if (col == maxLeft) {
dir = 1;
maxLeft++;
i--;
} else col--;
}
else if (dir == 1) {
if (row == maxTop) {
dir = 3;
maxTop++;
i--;
} else row--;
}
else {
if (col == maxRight) {
dir = 0;
maxRight--;
i--;
} else col++;
}
}
cout << result;
}
int main() {
routeCipher();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment