note: the letters are there twice so when shifting a letter at the end of the alphabet i dont get a out of range error
so currently im working on a caesers cypher where you write a word and shift those letters by a certain amount of times
input = abc
output = bcd
my issue is when the code runs it prints the output letters twice
input = abc
output = bbccdd
heres my code
alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
direction = input("Type 'encode' to encrypt, type 'decode' to decrypt:\n")
text = input("Type your message:\n").lower()
shift = int(input("Type the shift number:\n"))
def encrypt(text, shift):
cipher_text = ""
for i in text:
for letter in alphabet:
if i == letter:
index = alphabet.index(letter)
shifted_index = index shift
shifted_letter = alphabet[shifted_index]
cipher_text = shifted_letter
print(f"The encoded word is {cipher_text}")
encrypt(text, shift)
another example
input = zulu
expected output = avmv
code output = aavvmmvv
CodePudding user response:
Lots of work for what is essentially a one-liner:
import string
alphabet = string.ascii_lowercase # use the predefined string of lower case letters from the string module
index = {ch: i for i, ch in enumerate(alphabet)} # pre-calculate the index of each character once.
def encrypt(txt, n):
return ''.join(alphabet[(index[c] n) % len(alphabet)] for c in txt)
print(encrypt('spin', 5))
prints
xuns
the modulo operation (ie. ... % len(alphabet)
) makes sure the index is within bounds of the alphabet after adding the shift - no matter how big the shift is.
CodePudding user response:
leave it at "for i in text" their is no need for "for letter in alphabet" that is why it is looping through. If that doesnt work take out the duplicates in your alphabet. I didnt notice that on first glance.
CodePudding user response:
As mentioned above, you have the same alphabet twice. So, you need to exit the inner for loop once you have shifted. So, add a break
after cipher_text = shifted_letter
, that will exit the inner for loop.
Updated Code
alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
direction = input("Type 'encode' to encrypt, type 'decode' to decrypt:\n")
text = input("Type your message:\n").lower()
#shift = int(input("Type the shift number:\n"))
def encrypt(text, shift):
cipher_text = ""
for i in text:
for letter in alphabet:
if i == letter:
index = alphabet.index(letter)
shifted_index = index shift
shifted_letter = alphabet[shifted_index]
cipher_text = shifted_letter
break # NEW LINE
print(f"The encoded word is {cipher_text}")
shift = int(input("Type the shift number:\n"))
if shift > 26:
print("Shift should be max 26, exiting...")
else:
encrypt(text, shift)
Output
Type 'encode' to encrypt, type 'decode' to decrypt:
encode
Type your message:
spin
Type the shift number:
5
The encoded word is xuns
Updated based on feedback
import string
direction = input("Type 'encode' to encrypt, type 'decode' to decrypt:\n")
text = input("Type your message:\n").lower()
shift = int(input("Type the shift number:\n"))
alphabet = string.ascii_lowercase # use the predefined string of lower case letters from the string module
index = {ch: i for i, ch in enumerate(alphabet)} # pre-calculate the index of each character once.
def encrypt(txt, n):
return ''.join(alphabet[(index[c] n) % len(alphabet)] for c in txt)
encrypt(text, shift)
Output
Type 'encode' to encrypt, type 'decode' to decrypt:
encode
Type your message:
xylophone
Type the shift number:
100
'tuhkldkja'
CodePudding user response:
Remove the inner for
loop and the if
and then find the first index of the current character in the alphabet.
def encrypt(text, shift):
cipher_text = ""
for i in text:
index = alphabet.index(i)
shifted_index = index shift
shifted_letter = alphabet[shifted_index]
cipher_text = shifted_letter
print(f"The encoded word is {cipher_text}")
This code sticks closely to your approach. There are better solutions, like the one from @thebjorn.