Home > Enterprise >  for loop result is printed twice
for loop result is printed twice

Time:06-21

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.

  • Related