Created
March 14, 2024 18:11
-
-
Save AliBasicCoder/9bfd5eb03738580988cca8cb68faa9f1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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