Why wont my while loop work when adding my def function - python-3.x

This is my code below and I cant seem to make my while loop run continuosly.
#alphabet list
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']
# user input message
text = input("Type your message:\n")
# user input shift amount
shift = int(input("Type the shift number:\n"))
# def function
def encode(plain_text, shift_amount):
cipher_text = ''
for letter in plain_text:
position = alphabet.index(letter)
new_position = position + shift_amount
new_letter = alphabet[new_position]
cipher_text += new_letter
print(f'The encoded string is: {cipher_text}')
encode(plain_text = text, shift_amount = shift)
while True:
if text != 'q':
continue
I am not sure if I set this up correctly.

Executed like this, your prompt will ask for two inputs (your message and the shift number), then execute encode. Then it'll enter the while True loop and loop forever. Why?
Two reasons:
If you didn't input q at the first step, you will never meet the condition
Even though you did set text = "q", your loop will never stop. You need to use the break statement to make an infinite loop stop:
while True:
if text == 'q':
break
I think what you want is:
while True:
text = input("Type your message (or q to quit):\n")
shift = int(input("Type the shift number:\n"))
if text == 'q':
break
encode(text, shift_amount=shift)
Thus, your code will loop and ask & encode an input until to type "q"

You need to put the following lines inside the while loop for it to continuously run (as I think you want):
# user input message
text = input("Type your message:\n")
# user input shift amount
shift = int(input("Type the shift number:\n"))
encode(plain_text = text, shift_amount = shift)

As suggested in other answers, you should call input and encode inside the while loop. However, I think only the first input should be before the if clause like so:
while True:
# user input message
text = input("Type your message:\n")
if text != 'q':
break
# user input shift amount
shift = int(input("Type the shift number:\n"))
encode(plain_text=text, shift_amount=shift)
Also, you don't need to define alphabet as a list of characters, you can simply define it as a string:
alphabet = 'abcdefghifklmnopqrstuvwxyz'
or, even better, just import it from string:
import string
alphabet = string.ascii_lowercase

Related

IndexError: list index out of range - looping a list [duplicate]

This question already has answers here:
Caesar Cipher Function in Python
(27 answers)
Closed 13 days ago.
I have created a list with 26 items.
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']
I wish to use shift the letter to next selected position: i.e. "hello" to shift by position 5 and return me text as "mjqqt"
For which I have used the "for loop", and it works fine too until I use a letter z as it is the last item in the list.
Is there a way to loop the list once it has reached the alphabet[25] to restart to position alphabet[0], which means when the shift letter is "z" and shift by position 5 I want it to start again from position 0 to return "e"
I have created a function which for loop to shift each letter in the word and return the encrypted cipher_text.
def encrypt(plain_text, shift_amount):
cipher_text = ""
for letter in plain_text:
position = alphabet.index(letter)
new_position = position + shift_amount
cipher_text += alphabet[new_position]
print(f"The encoded text is {cipher_text}")
encrypt(plain_text=text, shift_amount=shift)
error:
Traceback (most recent call last):
File "\caesar-cipher\caesar-cipher-4 Final.py", line 36, in
encrypt(plain_text=text, shift_amount=shift)
IndexError: list index out of range
Pretty sure you can do that with modulo:
def encrypt(plain_text, shift_amount):
cipher_text = ""
for letter in plain_text:
position = alphabet.index(letter)
new_position = (position + shift_amount) % len(alphabet)
cipher_text += alphabet[new_position]
print(f"The encoded text is {cipher_text}")
This should work as you expect, you just loop the index if it is past the length of your alphabet

.append() is replacing element, instead of adding new element to the list

I am trying to create a cipher program, here text entered by the user will be shifted to the letters according to the shift variable. so here I have created an empty list called encrypt and trying to append characters after shifting them to the list.
But it's just replacing the letter in the list instead of adding a new item in the list.
Here's the 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']
#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"))
#TODO-1: Create a function called 'encrypt' that takes the 'text' and 'shift' as inputs.
def encrypt(text,shift):
for letter in text:
encrypted = []
position = alphabet.index(letter) + shift
encrypted.append(alphabet[position])
print(''.join(encrypted))
encrypt(text,shift)
Thank you
You are basically overwriting your list everytime in the loop. here
def encrypt(text,shift):
for letter in text:
encrypted = [] #This runs every iteration, so there will be only 1 at end
position = alphabet.index(letter) + shift
encrypted.append(alphabet[position])
print(''.join(encrypted))
Move it out of the loop, things must be fine.
def encrypt(text,shift):
encrypted = []
for letter in text:
position = alphabet.index(letter) + shift
encrypted.append(alphabet[position])
print(''.join(encrypted))

Why is this function just being skipped and not called?

I can't seem to see why this doesn't print each item in the loop. I ran it through Thonny and it just completely skips my function. Am I not passing in the variables/arguments correctly?
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']
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(direction, text, shift):
if direction == "encode":
for index, letter in enumerate(text):
print(letter)
I feel like I am messing up passing the values in from outside the function.
All you've done is define the function. You need to call it like
encrypt(direction, text, shift)
Right after you have gotten the input for those variables. Calling a function also needs to be done after it's defined, so you should move the function definition up at the top of the program.
Putting the names of parameters in the function definition doesn't "link" those to any variables named that in the rest of the program. Those parameters take on the value of whatever is passed in to the function. So for example, you could do
encrypt("encode", "hello", 3)
and then inside the function direction would be "encode", text would be "hello", and shift would be 3.

Pass cracker how not use four loops for four letters combination

I was practising for educational purpose with simply password cracker.
I know that I could use itertool but in my case when I'm learning I
would miss facing problems and learning on them and indeed I've met one
which is not giving me a peace.
What I want to learn is if I need get for example four combinations, so
how to get in a loop first letter 'a',then another step'a' and again 'a'
and 'a', to have 'aaaa' later on'abaa' etc.
So I wrote that:
import string
passe = 'zulu'
mylist = []
#letters = string.ascii_lowercase
letters = ['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 't', 'u', 'w', 'q', 'y', 'z']
mineset= set()
for a in letters:
for b in letters:
for c in letters:
for d in letters:
s = a + b + c + d
mylist.append(s)
mineset=set(mylist)
k = sorted(mineset)
print(k)
for i in k:
if i == passe:
print('got it: ', i )
print(passe in k)
It works in someway but the problems are:
I had to made a set from list because combinations
were repeated.
And finally, I was struggling with making it in without creating four
loops for four letters, something like that:
To try to solve those I went with that approach:
letters = ['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 't', 'u', 'w', 'q', 'y', 'z']
password = 'pass'
combin = ''
lista=[]
for x in range(1,5):
for y in letters:
combin +=y
lista.append(combin)
combin=''
mineset=set(lista)
print(mineset)
for i in lista:
if i == password:
print('pass:', i)
But the results are disspainting:
{'abc', 'a', 'ab', 'abcd', 'abcde'}
I was seating on it for a long day but can't even closely achieve
similar effect to 4 loops in previous code.
While I don't recommend this approach as a general rule, for purposes of learning here is a way to achieve what you want:
def getCombos(lts):
rslt = []
for l1 in lts:
for l2 in lts:
for l3 in lts:
for l4 in lts:
s = l1+l2+l3+l4
rslt.append(s)
return rslt
letters = 'abcdefghijklmnopqrstuvwxyz'
getCombos(letters)
As is illustrated by a simple example, this code is of O(n^x) in complexity where n = number of characters and x = length of the letters. This approach, quickly becomes unwieldly as the following example illustrates:
getCombos('abc")
yields 81 entries including:
['aaaa',
'aaab',
'aaac',
'aaba',
'aabb',
'aabc',
'aaca',
'aacb',
'aacc',
'abaa',
'abab',
'abac',
'abba',
'abbb',
'abbc',
'abca',
'abcb',
'abcc',
'acaa',
'acab',
'acac',
'acba',
'acbb',
'acbc',
'acca',
'accb',
'accc',
'baaa',
'baab',
'baac',
'baba',
'babb',
'babc',
'baca',
'bacb',
'bacc',
'bbaa',
'bbab',
'bbac',
'bbba',
'bbbb',
'bbbc',
'bbca',
'bbcb',
'bbcc',
'bcaa',
'bcab',
'bcac',
'bcba',
'bcbb',
'bcbc',
'bcca',
'bccb',
'bccc',
'caaa',
'caab',
'caac',
'caba',
'cabb',
'cabc',
'caca',
'cacb',
'cacc',
'cbaa',
'cbab',
'cbac',
'cbba',
'cbbb',
'cbbc',
'cbca',
'cbcb',
'cbcc',
'ccaa',
'ccab',
'ccac',
'ccba',
'ccbb',
'ccbc',
'ccca',
'cccb',
'cccc']

Appending list works for the first iteration but after I get list index out of range

I'm trying to make a Caesar cipher shift. Whenever I go about shifting the character based on the alphabet position it gives me the "list index out of range" error.
password = input('type in the word you want to turn into a password: ')
shift = int(input('What do you want your caesar shift to be? '))
new_password = []
password = list(password)
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']
i = 0
for num in range(0, len(password)):
for letter in alphabet:
i += 1
if password[num] == letter:
move = i
new_password.append(alphabet[(move + shift) - 1])
print(new_password[num])
I expected that this program would continue to continue to append letters to new_password based on how long the first password was. However after the first letter, I get the "list index out of range"
What's happening here is that your move and shift values end up being outside of the index values available in alphabet. You will need to add special cases to wrap around the indexes when (move + shift) - 1 is greater than the length of alphabet.

Resources