BananaBox
BananaBox

Reputation: 33

Caesar Cipher code only Ciphers one letter not entire string

So I'm in the middle of making a simple Caesar cipher for practice and I can't get it to decipher entire strings, just individual letters.

symbol_add is the function in question.

Here's the code:

import re

alphabet = "abcdefghijklmnopqrstuvwxyz"

def cleanIt(clean):
    global alphabet
    s = re.sub('[^a-z]+', '?', str(clean))
    return s

def symbol_add(symbol, key):
    encryptedMsg = ""
    for x in symbol:
        position = alphabet.find(x)
        newPosition = (position + key) % 26
        newLetter = alphabet[nyPosisjon]

    encryptedMsg += nyBokstav
    return encryptedMsg

def cipher(data,key):
    text = ""
    if data in alphabet:
        text += symbol_add(symbol=data,key=key)
        return text

def main():
    try:
        msg = (input("Write the message you would like to encrypt\n"))
        key = int(input("which key would you like to use?\n"))
        cleanIt(clean=msg)
        print(cipher(data=msg, key=key))
    except ValueError:
        print("Write a number!")

main()

I'm sure the solution is pretty simple, still learning.

Any help in how to solve this will be greatly appreciated!

Upvotes: 1

Views: 380

Answers (2)

rdimaio
rdimaio

Reputation: 325

import re

alphabet = "abcdefghijklmnopqrstuvwxyz"

def cleanIt(clean):
    global alphabet
    s = re.sub('[^a-z]+', '?', str(clean))
    return s

def symbol_add(symbol, key):
    position = alphabet.find(symbol)
    newPosition = (position + key) % 26
    newLetter = alphabet[newPosition]
    return newLetter

def cipher(data,key):
    text = ""
    for letter in data:
        if letter in alphabet:
            text += symbol_add(symbol=letter,key=key)
    return text

def main():
    try:
        msg = (input("Write the message you would like to encrypt\n"))
        key = int(input("which key would you like to use?\n"))
        # Note: you need to assign msg to be equal to cleanIt(clean=msg). 
        #       Just calling cleanIt(clean=msg) won't work, as strings 
        #       are immutable in Python
        msg = cleanIt(clean=msg)
        print(cipher(data=msg, key=key))
    except ValueError:
        print("Write a number!")

main()

The main changes are:

  • The for loop was moved from symbol_add to cipher, so that symbol_add gets called for each character
  • In main(): cleanIt(clean=msg) -> msg = cleanIt(clean=msg); the reason for this is that strings are immutable in Python, meaning that you need to reassign the variable msg to essentially point to the new string.

Output of this code:

Write the message you would like to encrypt
test
which key would you like to use?
1
uftu

Also, try to stick to a single naming convention; you have a function that follows camelCase (cleanIt) and another that follows snake_case (symbol_add). Try and name all functions in the same way. (The convention in Python is to use snake_case for functions)

Upvotes: 2

Patrick Artner
Patrick Artner

Reputation: 51643

You can streamline your cipher method quite a bit if you fill a dictionary as lookup when entering the method. It contains the mapping based on the key provided and maps your input characters to to the cipher-character.

Its much faster to look up in a dict then to .index() into a string.

Using dict.get(key[,default]) allows to provide the '?' for unknowns so you need no import re and no preprocessing.

Read about dict.get(): Why dict.get(key) instead of dict[key]?

Adding uppercase mapping to the chiffre is trivial as well based on the lower case ones:

alphabet = "abcdefghijklmnopqrstuvwxyz"

def cipher(data, key):
    # in case you change alphabet
    la = len(alphabet)

    # get the default lookup 
    chiffre = { c:alphabet[(i+key)%la] for i,c in enumerate(alphabet) }

    # create lookup for upper cases as well
    chiffre.update( { c.upper():n.upper() for c,n in chiffre.items() } )

    # supply ? for all unknowns, use the knowns where possible and return as string
    return ''.join( (chiffre.get(c,"?") for c in data) )

def main():
    try:
        msg = (input("Write the message you would like to encrypt\n"))
        key = int(input("which key would you like to use?\n"))

        print(cipher(data=msg, key=key))
    except ValueError:
        print("Write a number!")

main()

Output:

Write the message you would like to encrypt
Hello World
which key would you like to use?
1
Ifmmp?Xpsme

Upvotes: 1

Related Questions