Skip to content

Commit 4880931

Browse files
Add Polybius cipher (#5409)
* Add polybius cipher * Fix polybius.py build issues and add test
1 parent aa0ace4 commit 4880931

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed

ciphers/polybius.py

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#!/usr/bin/env python3
2+
3+
"""
4+
A Polybius Square is a table that allows someone to translate letters into numbers.
5+
6+
https://www.braingle.com/brainteasers/codes/polybius.php
7+
"""
8+
9+
import numpy as np
10+
11+
12+
class PolybiusCipher:
13+
def __init__(self) -> None:
14+
SQUARE = [
15+
["a", "b", "c", "d", "e"],
16+
["f", "g", "h", "i", "k"],
17+
["l", "m", "n", "o", "p"],
18+
["q", "r", "s", "t", "u"],
19+
["v", "w", "x", "y", "z"],
20+
]
21+
self.SQUARE = np.array(SQUARE)
22+
23+
def letter_to_numbers(self, letter: str) -> np.ndarray:
24+
"""
25+
Return the pair of numbers that represents the given letter in the
26+
polybius square
27+
>>> np.array_equal(PolybiusCipher().letter_to_numbers('a'), [1,1])
28+
True
29+
30+
>>> np.array_equal(PolybiusCipher().letter_to_numbers('u'), [4,5])
31+
True
32+
"""
33+
index1, index2 = np.where(self.SQUARE == letter)
34+
indexes = np.concatenate([index1 + 1, index2 + 1])
35+
return indexes
36+
37+
def numbers_to_letter(self, index1: int, index2: int) -> str:
38+
"""
39+
Return the letter corresponding to the position [index1, index2] in
40+
the polybius square
41+
42+
>>> PolybiusCipher().numbers_to_letter(4, 5) == "u"
43+
True
44+
45+
>>> PolybiusCipher().numbers_to_letter(1, 1) == "a"
46+
True
47+
"""
48+
letter = self.SQUARE[index1 - 1, index2 - 1]
49+
return letter
50+
51+
def encode(self, message: str) -> str:
52+
"""
53+
Return the encoded version of message according to the polybius cipher
54+
55+
>>> PolybiusCipher().encode("test message") == "44154344 32154343112215"
56+
True
57+
58+
>>> PolybiusCipher().encode("Test Message") == "44154344 32154343112215"
59+
True
60+
"""
61+
message = message.lower()
62+
message = message.replace("j", "i")
63+
64+
encoded_message = ""
65+
for letter_index in range(len(message)):
66+
if message[letter_index] != " ":
67+
numbers = self.letter_to_numbers(message[letter_index])
68+
encoded_message = encoded_message + str(numbers[0]) + str(numbers[1])
69+
elif message[letter_index] == " ":
70+
encoded_message = encoded_message + " "
71+
72+
return encoded_message
73+
74+
def decode(self, message: str) -> str:
75+
"""
76+
Return the decoded version of message according to the polybius cipher
77+
78+
>>> PolybiusCipher().decode("44154344 32154343112215") == "test message"
79+
True
80+
81+
>>> PolybiusCipher().decode("4415434432154343112215") == "testmessage"
82+
True
83+
"""
84+
message = message.replace(" ", " ")
85+
decoded_message = ""
86+
for numbers_index in range(int(len(message) / 2)):
87+
if message[numbers_index * 2] != " ":
88+
index1 = message[numbers_index * 2]
89+
index2 = message[numbers_index * 2 + 1]
90+
91+
letter = self.numbers_to_letter(int(index1), int(index2))
92+
decoded_message = decoded_message + letter
93+
elif message[numbers_index * 2] == " ":
94+
decoded_message = decoded_message + " "
95+
96+
return decoded_message

0 commit comments

Comments
 (0)