Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion python/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
# Python Instructions

- Ensure your code can run in the command-line with the command `python3 solution.py`
- Ensure your code can run in the command-line with the command `python3 solution.py`

## Explanation of the Python Solution

The Python solution in [`solution.py`](python/solution.py) is designed to decrypt a given Playfair Cipher string and output the decrypted text in accordance with the challenge requirements. Here's why it works effectively:

1. **Command-Line Execution**: The script is executable from the command line using `python3 solution.py`, as specified in the instructions. This ensures that the solution can be easily run and tested in a consistent environment.

2. **Decryption Logic**: At the core of `solution.py` is the decryption logic that accurately deciphers the encrypted Playfair Cipher text. This logic takes into account the unique aspects of the Playfair Cipher, such as the handling of digraphs (pairs of letters) and the special rules for decryption.

3. **Output Formatting**: The decrypted string is processed to meet the specific output requirements:
- The output is entirely in **UPPER CASE**.
- Spaces, the letter `"X"`, and special characters are removed from the output.
- The application outputs only the decrypted string, without any additional text or formatting.

4. **Automated Testing**: The accompanying [`solution.test.py`](python/solution.test.py) file contains a test case that verifies the output of the decryption script. This test ensures that the script produces the expected output `HIPPOPOTOMONSTROSESQUIPPEDALIOPHOBIA` when run. It serves as a validation of the solution's correctness.

By adhering to the challenge instructions and focusing on accurate decryption and proper output formatting, the Python solution effectively solves the given problem. The automated test provides an additional layer of confidence in the solution's reliability.
71 changes: 71 additions & 0 deletions python/solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import string

class PlayfairCipher:
"""
Playfair Cipher class

Attributes:
key -- the key used for encryption and decryption
matrix -- the 5x5 matrix used for encryption and decryption

Methods:
_prepare_key -- prepares the key by removing duplicates and replacing 'J' with 'I'
_create_matrix -- creates the 5x5 matrix from the key
_find_position -- finds the position of a letter in the matrix
decrypt -- decrypts the ciphertext using the Playfair Cipher
"""
def __init__(self, key):
self.key = self._prepare_key(key)
self.matrix = self._create_matrix()

def _prepare_key(self, key):
key = key.upper().replace('J', 'I')
return ''.join(dict.fromkeys(key + string.ascii_uppercase.replace('J', '')))

def _create_matrix(self):
return [list(self.key[i:i+5]) for i in range(0, 25, 5)]

def _find_position(self, letter):
for i, row in enumerate(self.matrix):
if letter in row:
return i, row.index(letter)
return None

def decrypt(self, ciphertext):
"""
Decrypts the ciphertext using the Playfair Cipher

Arguments:
ciphertext -- the text to be decrypted

Returns:
plaintext -- the decrypted text
"""
ciphertext = ciphertext.upper().replace('J', 'I')
plaintext = ""

for i in range(0, len(ciphertext), 2):
a, b = ciphertext[i], ciphertext[i+1]
row1, col1 = self._find_position(a)
row2, col2 = self._find_position(b)

if row1 == row2:
plaintext += self.matrix[row1][(col1-1)%5] + self.matrix[row2][(col2-1)%5]
elif col1 == col2:
plaintext += self.matrix[(row1-1)%5][col1] + self.matrix[(row2-1)%5][col2]
else:
plaintext += self.matrix[row1][col2] + self.matrix[row2][col1]

return plaintext.replace('X', '')

def main():
key = "SUPERSPY"
ciphertext = "IKEWENENXLNQLPZSLERUMRHEERYBOFNEINCHCV"

cipher = PlayfairCipher(key)
decrypted_text = cipher.decrypt(ciphertext)

print(decrypted_text, end='')

if __name__ == "__main__":
main()