Skip to content

Commit e504c69

Browse files
authored
flexible Baconian cipher encoding and decoding
Encodes and Decodes with any 2 symbols
1 parent e2a78d4 commit e504c69

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

ciphers/flexible_baconian_cipher

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
encode_dict = {
2+
"a": "AAAAA",
3+
"b": "AAAAB",
4+
"c": "AAABA",
5+
"d": "AAABB",
6+
"e": "AABAA",
7+
"f": "AABAB",
8+
"g": "AABBA",
9+
"h": "AABBB",
10+
"i": "ABAAA",
11+
"j": "BBBAA",
12+
"k": "ABAAB",
13+
"l": "ABABA",
14+
"m": "ABABB",
15+
"n": "ABBAA",
16+
"o": "ABBAB",
17+
"p": "ABBBA",
18+
"q": "ABBBB",
19+
"r": "BAAAA",
20+
"s": "BAAAB",
21+
"t": "BAABA",
22+
"u": "BAABB",
23+
"v": "BBBAB",
24+
"w": "BABAA",
25+
"x": "BABAB",
26+
"y": "BABBA",
27+
"z": "BABBB",
28+
" ": " ",
29+
}
30+
31+
decode_dict = {value: key for key, value in encode_dict.items()}
32+
33+
def encode(word: str, symbols=("A","B")) -> str:
34+
a_sym, b_sym = symbols
35+
encoded = ""
36+
for letter in word.lower():
37+
if letter.isalpha() or letter == " ":
38+
# replace A with a_symbol, B with b_symbol
39+
bacon = encode_dict[letter]
40+
bacon_custom = bacon.replace("A", a_sym).replace("B", b_sym)
41+
encoded += bacon_custom
42+
else:
43+
raise Exception("encode() accepts only letters of the alphabet and spaces")
44+
return encoded
45+
46+
def decode(coded: str, symbols=("A","B")) -> str:
47+
sym1, sym2 = symbols
48+
# check if we need to remap
49+
unique_symbols = set(coded.replace(" ", ""))
50+
if unique_symbols - {sym1, sym2} != set():
51+
raise Exception(f"decode() accepts only symbols {sym1} and {sym2} and spaces")
52+
53+
# Try both mappings: symbol1 maps to A, symbol2 maps to B or symbol1 maps to B, symbol2 maps A
54+
candidates = []
55+
for mapping in [(sym1, sym2), (sym2, sym1)]:
56+
s1, s2 = mapping
57+
# convert coded symbols to standard A/B
58+
standard = coded.replace(s1, "A").replace(s2, "B")
59+
try:
60+
decoded = ""
61+
for word in standard.split():
62+
while len(word) != 0:
63+
chunk = word[:5]
64+
if chunk not in decode_dict:
65+
raise ValueError
66+
decoded += decode_dict[chunk]
67+
word = word[5:]
68+
decoded += " "
69+
candidates.append(decoded.strip())
70+
except ValueError:
71+
candidates.append(None)
72+
73+
# return the valid decoding
74+
for candidate in candidates:
75+
if candidate is not None:
76+
return candidate
77+
raise Exception("No valid decoding found with the given symbols")
78+
def detect_unique_char (cipher):
79+
#CD CD DC returns C, D
80+
cipher = cipher.replace(" ","")
81+
unique_chars = set(cipher)
82+
unique_letters = [char for char in unique_chars if char.isalpha()]
83+
if len(unique_letters) != 2:
84+
raise Exception("Cipher must contain exactly two unique alphabetic characters for encoding.")
85+
else:
86+
list_unique = list(unique_letters)
87+
return list_unique[0], list_unique[1]
88+
89+
if __name__ == "__main__":
90+
# Example usage
91+
cipher_text = "FEEFE EEFFF EEFEE EFFFF FEEFF EFEEE EEEFE EFEEF EEEEF FEEEE EFFEF FEFEE EFFEE EEFEF EFFEF FEFEF"
92+
symbol_1, symbol_2 = detect_unique_char(cipher_text)
93+
decoded = decode(cipher_text, symbols=(symbol_1, symbol_2))
94+
print(decoded) # prints the quick brown fox

0 commit comments

Comments
 (0)