Skip to content
Closed
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
132 changes: 67 additions & 65 deletions ciphers/baconian_cipher.py
Original file line number Diff line number Diff line change
@@ -1,89 +1,91 @@
"""
Program to encode and decode Baconian or Bacon's Cipher
Wikipedia reference : https://en.wikipedia.org/wiki/Bacon%27s_cipher
Program to encode and decode using Baconian (Bacon's) Cipher.
Wikipedia reference: https://en.wikipedia.org/wiki/Bacon%27s_cipher
"""

# Dictionary for encoding letters into Baconian cipher
encode_dict = {
"a": "AAAAA",
"b": "AAAAB",
"c": "AAABA",
"d": "AAABB",
"e": "AABAA",
"f": "AABAB",
"g": "AABBA",
"h": "AABBB",
"i": "ABAAA",
"j": "BBBAA",
"k": "ABAAB",
"l": "ABABA",
"m": "ABABB",
"n": "ABBAA",
"o": "ABBAB",
"p": "ABBBA",
"q": "ABBBB",
"r": "BAAAA",
"s": "BAAAB",
"t": "BAABA",
"u": "BAABB",
"v": "BBBAB",
"w": "BABAA",
"x": "BABAB",
"y": "BABBA",
"z": "BABBB",
" ": " ",
"a": "AAAAA", "b": "AAAAB", "c": "AAABA", "d": "AAABB", "e": "AABAA",
"f": "AABAB", "g": "AABBA", "h": "AABBB", "i": "ABAAA", "j": "BBBAA",
"k": "ABAAB", "l": "ABABA", "m": "ABABB", "n": "ABBAA", "o": "ABBAB",
"p": "ABBBA", "q": "ABBBB", "r": "BAAAA", "s": "BAAAB", "t": "BAABA",
"u": "BAABB", "v": "BBBAB", "w": "BABAA", "x": "BABAB", "y": "BABBA",
"z": "BABBB", " ": " "
}


# Reverse dictionary for decoding Baconian cipher back into letters
decode_dict = {value: key for key, value in encode_dict.items()}


def encode(word: str) -> str:
"""
Encodes to Baconian cipher
Encodes a given word into Baconian cipher.

Check failure on line 22 in ciphers/baconian_cipher.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

ciphers/baconian_cipher.py:22:1: W293 Blank line contains whitespace
Only letters of the alphabet and spaces are accepted. Any other characters will raise a ValueError.

Check failure on line 23 in ciphers/baconian_cipher.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

ciphers/baconian_cipher.py:23:89: E501 Line too long (103 > 88)

Check failure on line 24 in ciphers/baconian_cipher.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

ciphers/baconian_cipher.py:24:1: W293 Blank line contains whitespace
Args:
word (str): The word or phrase to encode.

Check failure on line 27 in ciphers/baconian_cipher.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

ciphers/baconian_cipher.py:27:1: W293 Blank line contains whitespace
Returns:
str: The encoded message in Baconian cipher.

Check failure on line 30 in ciphers/baconian_cipher.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

ciphers/baconian_cipher.py:30:1: W293 Blank line contains whitespace
Raises:
ValueError: If the input contains characters other than letters and spaces.

>>> encode("hello")
'AABBBAABAAABABAABABAABBAB'
>>> encode("hello world")
'AABBBAABAAABABAABABAABBAB BABAAABBABBAAAAABABAAAABB'
>>> encode("hello world!")
Traceback (most recent call last):
...
Exception: encode() accepts only letters of the alphabet and spaces
Examples:
>>> encode("hello")
'AABBBAABAAABABAABABAABBAB'
>>> encode("hello world")
'AABBBAABAAABABAABABAABBAB BABAAABBABBAAAAABABAAAABB'
>>> encode("hello world!")
Traceback (most recent call last):
...
ValueError: encode() accepts only letters of the alphabet and spaces
"""
encoded = ""
encoded = []
for letter in word.lower():
if letter.isalpha() or letter == " ":
encoded += encode_dict[letter]
if letter in encode_dict:
encoded.append(encode_dict[letter])
else:
raise Exception("encode() accepts only letters of the alphabet and spaces")
return encoded

raise ValueError("encode() accepts only letters of the alphabet and spaces")
return ''.join(encoded)

def decode(coded: str) -> str:
"""
Decodes from Baconian cipher
Decodes a Baconian cipher message back into plain text.

Check failure on line 55 in ciphers/baconian_cipher.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

ciphers/baconian_cipher.py:55:1: W293 Blank line contains whitespace
The message must contain only 'A', 'B', and spaces. Other characters will raise a ValueError.

Check failure on line 56 in ciphers/baconian_cipher.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

ciphers/baconian_cipher.py:56:89: E501 Line too long (97 > 88)

Check failure on line 57 in ciphers/baconian_cipher.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

ciphers/baconian_cipher.py:57:1: W293 Blank line contains whitespace
Args:
coded (str): The encoded message to decode.

Check failure on line 60 in ciphers/baconian_cipher.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

ciphers/baconian_cipher.py:60:1: W293 Blank line contains whitespace
Returns:
str: The decoded plain text message.

Check failure on line 63 in ciphers/baconian_cipher.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

ciphers/baconian_cipher.py:63:1: W293 Blank line contains whitespace
Raises:
ValueError: If the input contains characters other than 'A', 'B', and spaces.

>>> decode("AABBBAABAAABABAABABAABBAB BABAAABBABBAAAAABABAAAABB")
'hello world'
>>> decode("AABBBAABAAABABAABABAABBAB")
'hello'
>>> decode("AABBBAABAAABABAABABAABBAB BABAAABBABBAAAAABABAAAABB!")
Traceback (most recent call last):
...
Exception: decode() accepts only 'A', 'B' and spaces
Examples:
>>> decode("AABBBAABAAABABAABABAABBAB BABAAABBABBAAAAABABAAAABB")
'hello world'
>>> decode("AABBBAABAAABABAABABAABBAB")
'hello'
>>> decode("AABBBAABAAABABAABABAABBAB BABAAABBABBAAAAABABAAAABB!")
Traceback (most recent call last):
...
ValueError: decode() accepts only 'A', 'B' and spaces
"""
if set(coded) - {"A", "B", " "} != set():
raise Exception("decode() accepts only 'A', 'B' and spaces")
decoded = ""
if set(coded) - {"A", "B", " "}:
raise ValueError("decode() accepts only 'A', 'B' and spaces")

decoded = []
for word in coded.split():
while len(word) != 0:
decoded += decode_dict[word[:5]]
word = word[5:]
decoded += " "
return decoded.strip()

for i in range(0, len(word), 5):
chunk = word[i:i+5]
decoded.append(decode_dict.get(chunk, ''))
decoded.append(' ') # Add space between words

return ''.join(decoded).strip()

if __name__ == "__main__":
from doctest import testmod

testmod()