Baconian Cipher Python Implementation I have been trying to implement various substitution ciphers in python. I implemented the Baconian cipher using a dictionary in which the plaintext letters are keys and the ciphertext letters are the corresponding values. Is there a way to make the following code shorter or more efficient or is there a better approach to implementing the cipher.
Python program to implement Baconian cipher
'''This script uses a dictionary instead of 'chr()' &amp; 'ord()' function'''

'''
Dictionary to map plaintext with ciphertext
(key:value) =&gt; (plaintext:ciphertext)
This script uses the 26 letter baconian cipher
in which I,J &amp; U,V have distinct patterns
'''
lookup = {'A':'aaaaa', 'B':'aaaab', 'C':'aaaba', 'D':'aaabb','E':'aabaa',
    'F':'aabab', 'G':'aabba', 'H':'aabbb', 'I':'abaaa', 'J':'abaab',
    'K':'abaab', 'L':'ababa', 'M':'ababb', 'N':'abbaa', 'O':'abbab',
    'P':'abbba', 'Q':'abbbb', 'R':'baaaa', 'S':'baaab', 'T':'baaba',
    'U':'babaa', 'V':'babab', 'W':'babaa', 'X':'babab', 'Y':'babba' 
    'Z':'babbb'}
#Function to encrypt the string according to the cipher provided
def encrypt(message):
    cipher = ''
    for letter in message:
        #checks for space
        if(letter != ' '):
            #adds the ciphertext corresponding to the plaintext from the dictionary
            cipher += lookup[letter]
        else:
            #adds space
            cipher += ' '

    return cipher

#Function to decrypt the string according to the cipher provided
def decrypt(message):
    decipher = ''
    i = 0

    #emulating a do-while loop
    while True :
        #condition to run decryption till the last set of ciphertext
        if(i &lt; len(message)-4):
            #extracting a set of ciphertext from the message
            substr = message[i:i+5]
            #checking for space as the first character of the substring
            if(substr[0] != ' '):
                '''
                This statement gets us the key(plaintext) using the values(ciphertext)
                Just the reverse of what we were doing in encrypt function
                '''
                decipher += list(lookup.keys())[list(lookup.values()).index(substr)]
                i += 5 #to get the next set of ciphertext
            else:
                #adds space
                decipher += ' '
                i += 1 #index next to the space
        else:
            break #emulating a do-while loop

    return decipher

def main():
    message = &quot;ALICE KILLED BOB&quot;
    result = encrypt(message.upper())
    print (result)

    message = &quot;aaaaaababaabaaaaaabaaabaa abaababaaaababaababaaabaaaaabb aaaababbabaaaab&quot;
    result = decrypt(message.lower())
    print (result)

#Executes the main function
if __name__ == '__main__':
    main()

I have been implementing most of the substitution ciphers using dictionaries and I want to know is there a another approach to this as I am bored of using dictionaries.
Bug
Letters J &amp; K, U &amp; W, and V &amp; X have the same pattern. This is not what the specification says: either I &amp; J and U &amp; V shares the same pattern, or none of the letters do.
Style
String literals ain't comments. If you want two lines of comments, you start your two lines with a # each. Also take the habit to put a space after the # sign, it eases readability.
You also don't need to put parentheses around simple conditions.
Lastly, PEP 8 recommends to use ALL_CAPS to name constants, like LOOKUP.
Generators
Concatenating strings using += is slow as strings are immutables and Python need to copy the whole string each time you add a bit at the end. For better performances, it is advised to use ''.join. To do this, it is easier to separate each function into two: one that iterates over the input and joins the converted output, the other that generates the converted output. Something like:
def encrypt_letter(letter):
    &quot;&quot;&quot;Convert a plain-text ascii letter into its Bacon's form.

    Let symbols and non ascii letter fail through gracefully.
    &quot;&quot;&quot;
    return LOOKUP.get(letter.upper(), letter.lower())


def encrypt(message):
    &quot;&quot;&quot;Encrypt a message using Bacon's cipher&quot;&quot;&quot;
    return ''.join(map(encrypt_letter, message))

One more thing to note with this implementation: you shouldn't require that the input is properly formatted, you should enforce it in your functions (usage of upper and lower within your function, not before its call)
Do-while
In Python, a do-while loop is emulated using something along the lines of:
while True:
    do_something()
    if ...:
        break

In your case, having the if directly as the first action of the while and an else: break, you just need a simple while loop:
while i &lt; len(message) - 4:
    substr = message[i:i + 5]
    ...