-5

I am trying to make the Vigenere cipher in python. I found some code on the internet that I was going to work around as it was hard. When I run this code:

plaintext = "HELLO WORLD"
keyword = "KEYKEYKEYKEY"
encoded = ""

for c in range(len(plaintext)):
    char = ord(plaintext[c])
    temp = ord(keyword[c])
    newchar = char + temp
    if newchar > ord("Z"):
        newchar -= 26
    newnewchar = chr(newchar)
    encoded += newnewchar

print(repr(encoded))

It prints out this:

'yp\x8b}z_\x88z\x91}o'

I was expecting only English letters. Any idea what could be wrong?

Terry Jan Reedy
  • 18,414
  • 3
  • 40
  • 52
  • 2
    I've edited your question and code so that people can quickly see what they need to know instead of having to open a pastebin link, copy code to their computer, run it, and enter input which may or may not reproduce the problem. I've also cut out the part of the code which was working so that there's less to read. Take note: this is how to ask a question on StackOverflow. Imagine how much easier it is for readers now. – Alex Hall May 11 '16 at 17:27

2 Answers2

2

Try out PyCharm, and learn to use the debugger. Running your code in it revealed the problem very easily:

enter image description here

(The highlighted line is where the code currently is, hence newchar == 121 == 72 + 75 - 26)

Even without PyCharm, the lesson is that when you need to figure out a problem in code, find a way to see what the values are at each stage to test your assumptions. The simplest way is to insert print(...) everywhere.

Alex Hall
  • 34,833
  • 5
  • 57
  • 89
  • 2
    As my teacher said whenever you asked for help with debugging, "first add print statements, to look for things that don't make sense. If you still can't find the problem, then come to me" – PMARINA May 11 '16 at 19:56
1

A more pythonic way would be to use list comprehensions;

plaintext = 'THISISAPLAINTEXT'
key = 'SPAMEGGS'
count = int(len(plaintext)/len(key))+1

stretchedkey = [ord(c) for c in key*count]

# Encryption
plainnum = [ord(c) for c in plaintext]
ciphernum = [a+b-65 for a, b in zip(plainnum, stretchedkey)]
ciphertext = ''.join([chr(c) if c <= 90 else chr(c-26) for c in ciphernum])

# Decryption
ciphernum = [ord(c) for c in ciphertext]
decryptnum = [a-b+65 for a, b in zip(ciphernum, stretchedkey)]
decrypt = ''.join([chr(c) if c >= 65 else chr(c+26) for c in decryptnum])

Showing the steps in IPython;

In [1]: plaintext = 'THISISAPLAINTEXT'

In [2]: key = 'SPAMEGGS'

In [3]: count = int(len(plaintext)/len(key))+1

In [4]: stretchedkey = [ord(c) for c in key*count]

In [5]: plainnum = [ord(c) for c in plaintext]

In [6]: plainnum
Out[6]: [84, 72, 73, 83, 73, 83, 65, 80, 76, 65, 73, 78, 84, 69, 88, 84]

In [7]: ciphernum = [a+b-65 for a, b in zip(plainnum, stretchedkey)]

In [8]: ciphernum
Out[8]: [102, 87, 73, 95, 77, 89, 71, 98, 94, 80, 73, 90, 88, 75, 94, 102]

In [9]: ciphertext = ''.join([chr(c) if c <= 90 else chr(c-26) for c in ciphernum])

In [10]: ciphertext
Out[10]: 'LWIEMYGHDPIZXKDL'

In [11]: ciphernum = [ord(c) for c in ciphertext]

In [12]: decryptnum = [a-b+65 for a, b in zip(ciphernum, stretchedkey)]

In [13]: decryptnum
Out[13]: [58, 72, 73, 57, 73, 83, 65, 54, 50, 65, 73, 78, 84, 69, 62, 58]

In [14]: decrypt = ''.join([chr(c) if c >= 65 else chr(c+26) for c in decryptnum])

In [15]: decrypt
Out[15]: 'THISISAPLAINTEXT'
Roland Smith
  • 42,427
  • 3
  • 64
  • 94