What's Wrong With My Vigenere Cypher Encrypt Function?
Solution 1:
You are going out-of-bounds by using the iterator in rot[i]
in line 36 of your program - i
will go up to the length of your plaintext, which can be larger than the key.
Try doing a module-div by length of the key, that way you should wrap around the key nicely:
lis.append(rotate_character(text[i], alphabet_position(rot[i % len(rot)])))
Edit You were still unhappy with the result your script returned, so I dug a bit deeper. The underlying problem is that you are trying to implement what some online-tools for Vigenere call "enhanced mode": neither plain- nor ciphertext are guarenteed to be from [a-zA-Z]
, but may "special characters", e.g. elements from [0-9]
or characters like <space>
, <
, etc.
In case your script encounters a special character, it will not rotate it, but rather copy it over as-is, as done in the else
-branch of rotate_character
; this is correct. In encrypt()
, however, you consume what we shall call a "keysymbol" for every symbol of the plaintext you encounter. This means that effectively you are "wasting" a keysymbol on a plaintext symbol that will not be encrypted (vulgo rotated) at all.
Once you realize this, the fix becomes evident: when we encounter a special character, copy it over into the output list, but don't advance the keystream. The keystream should only be advanced if we actually need to consume a keysymbol.
Translated into code:
def encrypt(text, rot):
lis = []
keystream = 0
for i in range(len(text)):
keychar = keystream % len(rot)
if text[i].isalpha():
lis.append(rotate_character(text[i], alphabet_position(rot[keychar])))
keystream += 1
else:
lis.append(text[i])
return (''.join(lis))
Post a Comment for "What's Wrong With My Vigenere Cypher Encrypt Function?"