// PLAYFAIR CIPHER
#include <iostream>
#include <string>
#include <vector>
#include <cctype>
using namespace std;
// Generate the 5x5 key table
void generateKeyTable(const string &key, char table[5][5]) {
bool used[26] = {};
string processedKey = "";
for (char c : key) {
c = tolower(c == 'j' ? 'i' : c);
if (isalpha(c) && !used[c - 'a']) {
processedKey += c;
used[c - 'a'] = true;
}
}
for (char c = 'a'; c <= 'z'; ++c) {
if (c == 'j') continue;
if (!used[c - 'a']) {
processedKey += c;
used[c - 'a'] = true;
}
}
int idx = 0;
for (int i = 0; i < 5; ++i)
for (int j = 0; j < 5; ++j)
table[i][j] = processedKey[idx++];
}
// Find character positions in key table
void findPosition(char table[5][5], char ch, int &row, int &col) {
if (ch == 'j') ch = 'i';
for (int i = 0; i < 5; ++i)
for (int j = 0; j < 5; ++j)
if (table[i][j] == ch) {
row = i;
col = j;
return;
}
}
// Prepare the text (insert 'x' for repeated pairs, pad with 'z' if odd length)
string prepareText(string text) {
string result = "";
for (char c : text)
if (isalpha(c)) result += tolower(c == 'j' ? 'i' : c);
string finalText = "";
for (size_t i = 0; i < result.length(); ++i) {
finalText += result[i];
if (i + 1 < result.length()) {
if (result[i] == result[i + 1])
finalText += 'x';
else
finalText += result[++i];
}
}
if (finalText.length() % 2) finalText += 'z';
return finalText;
}
// Encrypt using Playfair cipher
string encrypt(const string &text, const string &key) {
char table[5][5];
generateKeyTable(key, table);
string prepared = prepareText(text), cipher = "";
for (size_t i = 0; i < prepared.length(); i += 2) {
int r1, c1, r2, c2;
findPosition(table, prepared[i], r1, c1);
findPosition(table, prepared[i + 1], r2, c2);
if (r1 == r2) {
cipher += table[r1][(c1 + 1) % 5];
cipher += table[r2][(c2 + 1) % 5];
}
else if (c1 == c2) {
cipher += table[(r1 + 1) % 5][c1];
cipher += table[(r2 + 1) % 5][c2];
}
else {
cipher += table[r1][c2];
cipher += table[r2][c1];
}
}
return cipher;
}
// Decrypt using Playfair cipher
string decrypt(const string &cipher, const string &key) {
char table[5][5];
generateKeyTable(key, table);
string plain = "";
for (size_t i = 0; i < cipher.length(); i += 2) {
int r1, c1, r2, c2;
findPosition(table, cipher[i], r1, c1);
findPosition(table, cipher[i + 1], r2, c2);
if (r1 == r2) {
plain += table[r1][(c1 + 4) % 5];
plain += table[r2][(c2 + 4) % 5];
}
else if (c1 == c2) {
plain += table[(r1 + 4) % 5][c1];
plain += table[(r2 + 4) % 5][c2];
}
else {
plain += table[r1][c2];
plain += table[r2][c1];
}
}
return plain;
}
int main() {
string key = "Monarchy";
string plaintext = "instruments";
cout << "Key: " << key << "\nPlaintext: " << plaintext << endl;
string ciphertext = encrypt(plaintext, key);
cout << "Ciphertext: " << ciphertext << endl;
string decrypted = decrypt(ciphertext, key);
cout << "Decrypted: " << decrypted << endl;
return 0;
}