1

I am coding a Caesar cipher. The key is an integer from 1 to 25. This cipher rotates the letters of the alphabet (A to Z). The encoding replaces each letter with the 1st to 25th next letter in the alphabet (wrapping Z to A). So key 2 encrypts “HI” to “JK”, but key 20 encrypts “HI” to “BC”.

But If I put in "I am super" it will output "k kc oouwrgt" when it should be "k co uwrgt" with a key of 2. It will also not go back to the beginning of the alphabet e.g 'x' will not go to 'a' with a key of 2. I use python 3.4.1

encode = []
a = "abcdefghijklmnopqrstuvwyxz"
a = list(a)
print(a)

e = input("encode or decode --->")
text = input("Sentence -->").lower()
text = list(text)
print(text)


Key = int(input("Key -->"))
if Key > 25:
    print("Too high")
else:
   print(Key)

if e == "encode":
    for i, item in enumerate(text):
        if item == " ":
            encode.append(letter)
        else:
            num = a.index(item)
            num = num + int(Key)
            letter = a[num]
            encode.append(letter)

for i in range(len(encode)):
    print(encode[i])
alexwlchan
  • 5,699
  • 7
  • 38
  • 49
jennmaurice
  • 77
  • 1
  • 1
  • 8

2 Answers2

4

When you encounter a space, you append the last letter again, instead of item:

if item == " ":
    encode.append(letter)

This causes k and o to appear twice when the key is 2; you re-appended the encoded i -> k and m -> o results.

You need to use the % modulo operator to make your index 'wrap round':

num = (num + Key) % 26

I removed the int() call, you already turned Key to an integer earlier.

Other tips:

  • You don't need to turn a into a list; strings are sequences too and support indexing and the .index()method directly. The same applies to text; just loop over the string itself.

  • You are not using i in the for i, item in enumerate(text): loop; drop enumerate altogether: for item in text:.

  • You could just print your encoded characters directly in that loop, no need to use an encode list and a separate loop.

  • The str.join() method would let you print your encoded text all on one line: print(''.join(encode)) instead of your last for loop.

  • The absolute fastest method of encoding a string is to use a translation table, a dictionary mapping input characters to output characters, and the str.translate() method. You can use the str.maketrans() function to make that table:

    import string
    
    a = string.ascii_lowercase  # why type yourself when the stdlib has these?
    text = input("Sentence -->").lower()
    Key = int(input("Key -->"))
    mapping = str.maketrans(a, a[Key:] + a[:Key])  # letters to rotated letters
    print(text.translate(mapping))
    

    The trick lies in creating the second string for str.maketrans(); using slicing it is easy to create a rotated string, by taking everything from position Key onwards, and the first Key characters at the end:

    >>> a[Key:] + a[:Key]
    'cdefghijklmnopqrstuvwyxzab'
    
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
0

One obvious solution would be to use modulo for the alphabet index:

The % (modulo) operator yields the remainder from the division of the first argument by the second.

>>> 12 % 26
12
>>> 26 % 26
0
>>> 28 % 26
2

As a bonus, you wouldn't need to check the key is lower than 25, and you'll never get an IndexError: list index out of range.

encode = []
a = "abcdefghijklmnopqrstuvwyxz"

e = input("encode or decode --->")
text = input("Sentence -->").lower()

key = int(input("Key -->"))

if e == "encode":
    for i, item in enumerate(text):
        if item == " ":
            encode.append(item)
        else:
            num = a.index(item)
            num = num + int(key)
            letter = a[num % 26]
            encode.append(letter)

for letter in encode:
    print(letter)

A few notes:

  • a string is already an iterable of characters. No need to convert it to a list
  • letter wasn't defined in if item == " "
  • to iterate over a list, you don't need the length or the index.
  • to decode the message, just change the sign of the key. It should work just like encode, thanks to modulo : -2 % 26 # => 24

As an example:

encode or decode --->encode
Sentence -->i am super
Key -->2
k

c
o

u
w
r
g
t

and

encode or decode --->encode
Sentence -->k co uwrgt
Key -->-2
i

a
m

s
u
p
e
r
Community
  • 1
  • 1
Eric Duminil
  • 52,989
  • 9
  • 71
  • 124