Search code examples
python-3.xvigenere

How can I make my Vigenère cipher handle spaces in the message?


This is the function I am using to handle the Vigenére cipher. My issue is that if I have any spaces in the input, they will be encoded together with the message. I want to have the spaces in the output message unaltered. How can I do that?

def vigenere():
    global encoded
    global message
    global book

    while len(book) < len(message):
        book += book

    book = book[:len(message)]

    encoded = ""

    for char in range(len(message)):
        newchar = ord(message[char]) + ord(book[char]) - 194
        newchar %= 25
        encoded += chr(newchar + 97)

    print(encoded)

Solution

  • Before using your Vigenère cipher, get all the places in your string where spaces appear. You can do that by using regular expressions:

    import re    
    
    def space_indices(string):
      return [s.start() for s in re.finditer(' ', string)]
    

    Then, remove all spaces from your input:

    def remove_spaces(string):
      return string.replace(' ', '')
    

    And redefine your Vigenère cipher function so that it returns the encoded message instead of printing it:

    def vigenere(): 
      # encode your message...
      return encoded
    

    You can then define a new function which will find the indices of all spaces, save those indices, remove the spaces, apply the Vigenère cipher on the unspaced string, and then insert the spaces back into the result:

    def space_preserving_vigenere(message):
      space_indices = space_indices(message)
      unspaced_msg = remove_spaces(message)
      encoded = vigenere(unspaced_msg)
      inserted_spaces = 0
      for index in space_indices:
        actual_index = index + inserted_spaces
        encoded = encoded[:actual_index] + ' ' + encoded[actual_index:]
        inserted_spaces = inserted_spaces + 1
      return encoded