1

I struck a brick wall trying to solve this and I am not sure how to approach this problem.

My idea is to compare both first characters of each string and if they are the same, save the character in the alphabet string of the index position shift. Recurse the rest of the string by removing the first character of the secret. If the first characters are different, recurse but removing the first character of the alphabet string.

I am not sure how to recurse for the rest of the alphabet though.

alphabet = "abcdefghijklmnopqrstuvwxyz"

def caesar_encrypt(secret, shift):
    if len(secret) == 0:
        return "" 
    elif shift == 0:
        return secret
    else:
        if secret[0] == alphabet[0]:           
            return alphabet[shift] + caesar_encrypt(secret[1:],shift)
        else:
            return caesar_encrypt(secret,shift), alphabet[1:]
rayryeng
  • 102,964
  • 22
  • 184
  • 193
  • If you are providing a variable key to the encryptor, then how is it a caesar cipher? It should be a modified caesar cipher. (caesar cipher key=3 ; modified caesar cipher key= 1-25) – Vasu Deo.S Jun 03 '19 at 03:12

2 Answers2

1

I would suggest using str.index to find the index of where each character is in the alphabet for each character in your string. After, use this to index into the alphabet and recurse.

A couple of gotchas that you should look out for:

  1. If the string contains a space, place this space as is in the string then move onto the next character

  2. You need to handle wraparound where if we're at the end of the alphabet and you choose a shift that would exceed the end of the alphabet, you need to wrap around and go to the beginning of the alphabet.

This should work:

alphabet = "abcdefghijklmnopqrstuvwxyz"

def caesar_encrypt(secret, shift):
    if len(secret) == 0:
        return ""
    elif shift == 0:
        return secret
    elif secret[0] == ' ': # New - handle spaces
        return ' ' + caesar_encrypt(secret[1:], shift)
    else:
        index = (alphabet.index(secret[0]) + shift) % len(alphabet) # Find the right place to access the alphabet
        return alphabet[index] + caesar_encrypt(secret[1:], shift) # Use this new character then recurse

NB: This implementation only handles lowercase letters.

rayryeng
  • 102,964
  • 22
  • 184
  • 193
0

How about this:

def shift_alphabet(shift):
    return alphabet[shift:] + alphabet[:shift]

def caesar_encrypt(secret, shift):
    coded_alphabet = shift_alphabet(shift)
    coded = [coded_alphabet[alphabet.index(i)] for i in secret]
    coded = ''.join(coded)

    return coded

Using map/lambda instead of for:

def shift_alphabet(shift):
      return alphabet[shift:] + alphabet[:shift]

def encrypt_letter(letter, coded_alphabet):
      return coded_alphabet[alphabet.index(letter)]

def caesar_encrypt(secret, shift):
      coded_alphabet = shift_alphabet(shift)
      coded = map(lambda x: encrypt_letter(x, coded_alphabet), secret)
      coded = ''.join(coded)

      return coded
foxpal
  • 586
  • 4
  • 14
  • I see that you created a new alphabet, but what the ".index(i)] for i in secret" does? And, it is possible to use recursion instead of a for loop? like: if len(secret) == 0: return "" else: [code] return caesar_encrypt(secret[1:], shift) – Fernando Fuentes Martins Jun 03 '19 at 02:42
  • .index returns the index of the letter in the alphabet – foxpal Jun 03 '19 at 02:45