It seems like your current solution would require the person to look through all the possible decryptions and decide which one is right. That could work ok, but it might not be necessary. It could be possible for the program to figure it out itself.
Here’s an example of superb rain’s idea to assume the decryption with the most spaces is the correct one:
import string
encrypted_text = "fxeyaxklqxhkltkxqebobxtbobxplxjykvxfaflqpxfkxqebxtloiaxrkqfixfxpqyoqbaxrpfkdxqebxfkqbokbq"
ch_list = string.ascii_lowercase + ' '
def translation_maker(offset, ch_list):
translation_dict = dict()
for ind, ch in enumerate(ch_list):
translation_dict[ch] = ch_list[(ind + offset) % len(ch_list)]
return str.maketrans(translation_dict)
def translation_generator(text, ch_list):
for ind in range(len(ch_list)):
for offset in range(len(ch_list)):
yield text.translate(translation_maker(offset, ch_list))
likely_decryption = max(translation_generator(encrypted_text, ch_list), key=lambda x: x.count(' '))
print(likely_decryption)
# a lot of this could be one-lined, but it might maybe considered less readable
# e.g.:
"""
likely_decryption = max(
(
encrypted_text.translate(str.maketrans(
{
ch: ch_list[(ind + offset) % len(ch_list)]
for ind, ch in enumerate(ch_list)
}))
for offset in range(len(ch_list))
),
key=lambda x: x.count(' '))
"""
It prints the correct string in this case.
A different thing you could do is have a big set with every word in the English language, and assume the correct decryption is the one that has the most matches with the set after you split it by space. It would be mostly the same, but the lambda function would be changed to this:
key=lambda x: sum(word in word_set for word in x.split()))
This might be slower even when disregarding the creation of the word set, and it would obviously use more memory, but it would be more unlikely to give a wrong result.