using a while loop instead of for loop - python

secret_word = "python"
correct_word = "yo"
count = 0
for i in secret_word:
if i in correct_word:
print(i,end=" ")
else:
print('_',end=" ")
so the outcome of the code will look like this _ y _ _ o _
my question is how i can i get the same output by using while loop instead of using For loop. i know i have to use index to iterate over each character but when i tried i failed . so any help?
while count < len(secret_word):
if correct_word [count]in secret_word[count]:
print(correct_word,end=" ")
else:
print("_",end=" ")
count = count + 1
Thanks

You can do this:
secret_word = "python"
correct_word = "yo"
count = 0
while count < len(secret_word):
print(secret_word[count] if secret_word[count] in correct_word else '_', end=" ")
count += 1

Another way to use while is to simulate a pop of the first character. The while loop terminates when the 'truthiness' of a string becomes false with no more characters to process:
secret_word = "python"
correct_word = "yo"
while secret_word:
ch=secret_word[0]
secret_word=secret_word[1:]
if ch in correct_word:
print(ch,end=" ")
else:
print('_',end=" ")
Or, you can actually use a list with a LH pop:
secret_list=list(secret_word)
while secret_list:
ch=secret_list.pop(0)
if ch in correct_word:
print(ch,end=" ")
else:
print('_',end=" ")

Here is a simple, way of writing your program with a while loop instead of a for loop. The code breaks out of an infinite loop when appropriate.
def main():
secret_word = 'python'
correct_word = 'yo'
iterator = iter(secret_word)
sentinel = object()
while True:
item = next(iterator, sentinel)
if item is sentinel:
break
print(item if item in correct_word else '_', end=' ')
if __name__ == '__main__':
main()
It uses logic similar to how the for loop is implemented internally. Alternatively, the example could have used exception handling instead.

Related

(Python3) - Random number inserted at the end of only 1 word in a string of many words

I am trying to make a random word/phrase generator that is like the one that bitwarden has (in python3). But the issue I am running into and need some help with is the addition of 1 number at the end of 1 of the words that is shown.
Something like this Referee-Outrank-Cymbal-Cupping-Cresting-Fiber7-Expensive-Myth-Unveiling-Grasp-Badland-Epiphany-Simplify-Munchkin-Pastrami-Spiffy-Gladly-Skeptic-Retouch-Buckskin
What is very important here is that the number is "random" and the word it is attached to is "random".
Code I have written so far:
Word list I am using is https://svnweb.freebsd.org/csrg/share/dict/words?view=co&content-type=text/plain but without ' in any of the words.
#pycryptodome==3.15.0
from Crypto.Random import random
import beaupy
import os
def clear():
os.system('clear||cls')
def main():
while True:
try:
number = int(beaupy.prompt("How many words?: "))
except ValueError as e:
print(f'Oops! Something went wrong.\nError: {e}\n\n')
input('Press "enter" to continue...')
clear()
continue
if number > 20 or number < 3:
print("20 words is the maximum number of words you can use. And 5 words is the minimum.\n\n")
input('Press "enter" to continue...')
clear()
else:
break
cwd = os.getcwd()
word_path = f"{cwd}/words.txt"
with open(word_path, 'r') as fh:
words = fh.read().lower()
word_list = words.splitlines() #list of words
sep = beaupy.prompt('Line separator? (leave empty for default "-"): ')
if sep == '' or sep == ',':
sep = '-'
#Returns True or False. Basically Yes or No?
if beaupy.confirm("Capitalize?"):
"""Make list of words with the first letter capitalized."""
c_lst = []
for i in word_list:
c_lst.append(i.title())
capital_words = f'{sep}'.join(random.choice(c_lst) for _ in range(number))
else:
default_words = f'{sep}'.join(random.choice(word_list) for _ in range(number))
if beaupy.confirm("Number?"):
rn_num = random.randint(0, 9) # <-- Get a random number to be used with only 1 of the words defined in capital_words or default_words below.
#I don't know what to do here... but I need to have a version with the number and one without. (default)
if __name__ == '__main__':
clear()
main()
I am not exactly familiar with string manipulation and searching for answers online just isn't giving me any help with the very specific thing I'm trying to do. All I want is for 1 word in the resulting string to have a "random" number attached to it.
I don't know if I need to re order my code and have it be done a different way. I am having such a headache with this. Any help would be great.
Edit#1
Additional and unrelated note, If anyone knows of a better word list to use, please let me know!
If I am understanding correctly, here is a solution:
#Returns True or False. Basically Yes or No?
capital_words = ''
default_words = ''
if beaupy.confirm("Capitalize?"):
"""Make list of words with the first letter capitalized."""
c_lst = []
for i in word_list:
c_lst.append(i.title())
capital_words = f'{sep}'.join(random.choice(c_lst) for _ in range(number))
else:
default_words = f'{sep}'.join(random.choice(word_list) for _ in range(number))
if beaupy.confirm("Number?"):
rn_num = random.randint(0, 9) # <-- Get a random number to be used with only 1 of the words defined in capital_words or default_words below.
#I don't know what to do here... but I need to have a version with the number and one without. (default)
word_index = random.randint(0, number - 1) # Get random index that is in the word list
if default_words != '':
word_with_number = default_words.split(sep)
else:
word_with_number = capital_words.split(sep)
word_with_number[word_index] = word_with_number[word_index] + str(rn_num)
word_with_number = sep.join(word_with_number)
print(word_with_number)
if default_words != '':
print(default_words)
else:
print(capital_words)
OUTPUT:
detroit-elide-windbag-purge-tort-mortician-codex7-annex-fairy-suntanning
detroit-elide-windbag-purge-tort-mortician-codex-annex-fairy-suntanning
With some help from AnonymousFrog. I was able to get my code working.
The following is the now working code.
from Crypto.Random import random
import beaupy
import os
def clear():
os.system('clear||cls')
def main():
while True:
try:
number = int(beaupy.prompt("How many words?: "))
except ValueError as e:
print(f'Oops! Something went wrong.\nError: {e}\n\n')
input('Press "enter" to continue...')
clear()
continue
if number > 20 or number < 3:
print("20 words is the maximum number of words you can use. And 5 words is the minimum.\n\n")
input('Press "enter" to continue...')
clear()
else:
break
cwd = os.getcwd()
word_path = f"{cwd}/words.txt"
with open(word_path, 'r') as fh:
words = fh.read().lower()
word_list = words.splitlines() #list of words
sep = beaupy.prompt('Line separator? (leave empty for default "-"): ')
if sep == '' or sep == ',':
sep = '-'
#Returns True or False. Basically Yes or No?
capital_words = ''
default_words = ''
if beaupy.confirm("Capitalize?"):
"""Make list of words with the first letter capitalized."""
c_lst = []
for i in word_list:
if len(i) < 3 or len(i) > 9:
pass
else:
c_lst.append(i.title())
cap = True
capital_words = f'{sep}'.join(random.choice(c_lst) for _ in range(number))
else:
cap = False
default_words = f'{sep}'.join(random.choice(word_list) for _ in range(number))
if beaupy.confirm("Number?"):
num = True
rn_num = random.randint(0, 9) # <-- Get a random number to be used with only 1 of the words defined in capital_words or default_words below.
word_index = random.randint(0, number - 1) # Get random index that is in the word list
if default_words != '':
word_with_number = default_words.split(sep)
else:
word_with_number = capital_words.split(sep)
word_with_number[word_index] = word_with_number[word_index] + str(rn_num)
word_with_number = sep.join(word_with_number)
else:
num = False
if cap == True and num == False:
print(capital_words)
if cap == False and num == False:
print(default_words)
if num == True:
print(word_with_number)
Thanks for the help!
(if anyone knows of a better word list to use, feel free to let me know)

creating a program that needs to check if 2 lists match completely but not working for some reason

I need to check whether 2 lists match in order, e.g. ['h', 'i', '2'] and ['h', 'i', '2'] would be a match.
I am trying a range of things and am trying list1 == list2 but that doesnt work for some reason and im not too sure why.
I have also tried collection counters and that did work but it also worked for lists that werent in order so not useful
I have had to do some wierd layout stuff by changing it from tuples to lists but the lists match completely, they are just not flagged when they do match.
class passwordCracker:
def __init__(self, password):
self.password = password
self.characters = []
self.passwordLength = len(password)
def characterFinder(self):
letters = string.printable
letters = [char for char in letters]
start = time.time()
with open("common_passwords.csv") as f: #cracking password using a dictionary attack
reader = csv.reader(f)
commonWords = list(reader) #putting common passwords in a list
passwordList = [self.password]
print(passwordList)
counter = 0
found = False
for i in range(len(commonWords)): #looping through common passwords
lengthOfList = len(commonWords)
if commonWords[i] == passwordList: #if passwords match
print("password cracked: " + self.password)
end = time.time()
print(f"Password cracked in {end - start}") #print message
found = True
break #break from for loop
else:
counter = counter + 1
if counter == lengthOfList: #if end of list reached
break #break from for loop
# passwordSplit = [char for char in self.password]
passwordTuple = tuple(self.password)
count = 0
checker = 0
if found == False:
for i in range(0, len(letters)+1):
for x in itertools.combinations(letters, i):
if found == False:
count=count+1
print(count)
passwordTuple = list(passwordTuple)
print(passwordTuple)
variable = list(x)
print(variable)
if passwordTuple == variable:
for i in range(1000000):
print("HELLO")
print("password cracked: " + self.password)
end = time.time()
print(f"Password cracked in {end - start}") # print message
found = True
break # break from for loop
password = input("Please enter the tested password: ")
test2 = passwordCracker(password)
test2.characterFinder()
example list below
An easier way to do this could be by sorting the lists and then using Collections counter. Make sure you import collections
list1.sort()
list2.sort()
if collections.Counter(list1) == collections.Counter(list2):
print ("The lists are identical")
else :
print ("The lists are not identical")

Hangman prints word multiple times if a letter occurs multiple times

I am building a Hangman game. The code that I wrote prints the 'updated target word' multiple times if a letter occurs multiple times.
Example: the target word is 'celebrate'. If I guess e then it prints
*e******
*e*e****
*e*e***e
I would like to avoid printing the first two printouts and only print the third and most updated version.
import random
import re
word_list = ["fireboard", "identical", "chocolate", "christmas", "beautiful", "happiness", "wednesday", "challenge", "celebrate"]
random_pick = random.choice(word_list)
random_pick_a = re.sub("[a-z]","*", random_pick)
random_pick_list_a = list(random_pick_a)
print(random_pick)
count = 0
def main_function():
global count
while count <= 9:
user_input = str(input("type a letter:"))
for i, c in enumerate(random_pick):
if c == user_input.casefold():
random_pick_list_a[i] = user_input.casefold()
random_pick_list_b = ''.join(random_pick_list_a)
print(random_pick_list_b)
if random_pick_list_b == random_pick:
print("done")
exit()
else:
continue
else:
if user_input.casefold() not in random_pick:
count = count+1
print(count)
if count == 10:
print("sorry")
exit()
main_function()
Disclaimer: I am in my first weeks of coding!
No need to str() the input(), it's already a string. So strip str(input("type a letter:")) to input("type a letter:").
No need in
else:
continue
it will continue even without it. Don't use globals, just move your count into main_function().
Don't do if count == 10, you're already doing it in while count <= 9.
As for your question - move the block
print(random_pick_list_b)
if random_pick_list_b == random_pick:
print("done")
exit()
out of the for-loop. So the whole thing would look like this:
def main_function():
count = 0
while count <= 4:
user_input = input("type a letter:")
for i, c in enumerate(random_pick):
if c == user_input.casefold():
random_pick_list_a[i] = user_input.casefold()
random_pick_list_b = ''.join(random_pick_list_a)
print(random_pick_list_b)
if random_pick_list_b == random_pick:
print("done")
exit()
else:
if user_input.casefold() not in random_pick:
count = count+1
print(count)
print("sorry")
You have:
print(random_pick_list_b)
Inside the for loop that is checking each character for the chosen letter. So, it prints out random_pick_list_b every time it finds a match.
Move it to right after the for loop if you want to do it one time when the checking is complete.
I would do this check once before the for loop.

Python - Every other letter in a string capitalized within a loop where the data was handed down from a copied list of user input

I was instructed to have a user input at least 8 words into a list and then perform various manipulations to the data within the list. One of the manipulations it asks me to do is to create a loop that makes every other letter in the strings capitalized (hElLo WoRlD.) For better readability, I left out the other manipulations that I have done to the code.
import sys
def main():
words = []
wordCount = 0
userWord = input("Enter at least 8 words or 'bye' to leave the program: ").split(' ')
while True:
if len(userWord)<8:
print("Please print at least 8 words, try again.")
sys.exit()
elif wordCount >= 8 and userWord[wordCount] != 'bye':
words.append(userWord[wordCount])
wordCount = wordCount + 1
else:
break
every_other (userWord)
def every_other(words):
words6 = words.copy()
st = ""
for i in range(len(words6)):
if (i%2) == 0:
st += words6[i].upper()
else:
st += words6[i]
print ('This is your list with every other letter capitalized: ', words6)
return st
main()
I am not getting any error messages but the code doesn't seem to be running starting at def every_other.
You'll have to print the function every_other as it returns a string:
import sys
def main():
words = []
wordCount = 0
userWord = input("Enter at least 8 words or 'bye' to leave the program: ").split(' ')
while True:
if len(userWord)<8:
print("Please print at least 8 words, try again.")
sys.exit()
elif wordCount >= 8 and userWord[wordCount] != 'bye':
words.append(userWord[wordCount])
wordCount = wordCount + 1
else:
break
print('This is your list with every other letter capitalized: ', every_other(userWord))
def every_other(words):
words6 = words.copy()
st = ""
for i in range(len(words6)):
if (i%2) == 0:
st += words6[i].upper()
else:
st += words6[i]
return st
#print ('This is your list with every other letter capitalized: ', words6) # This will never run as the function has already returned
main()
If you want to capitalize every second character:
import sys
def main():
words = []
wordCount = 0
userWord = input("Enter at least 8 words or 'bye' to leave the program: ").split(' ')
while True:
if len(userWord)<8:
print("Please print at least 8 words, try again.")
sys.exit()
elif wordCount >= 8 and userWord[wordCount] != 'bye':
words.append(userWord[wordCount])
wordCount = wordCount + 1
else:
break
print('This is your list with every other letter capitalized: ', every_other(userWord))
def every_other(words):
st = ""
new_st = ""
for w in words:
st+=w
print(str(st))
for count, val in enumerate(st):
if (count % 2) == 0:
val = val.upper()
new_st+=val
return new_st
main()

Keep calling a function until a condition is met Python

I want to create a hangman game. I want it to keep calling x and printing new_word until there is no "_". I have tried it but the slots keep refreshing. It keeps reprinting. It won't update the value itself.
word = 'EVAPORATE'
wordlist = list(word)
dict = dict(enumerate(wordlist))
slots = list('_' * len(word))
x = input("Guess the letter: ")
def game():
for a,b in dict.items():
if b == x:
slots[a] = x
new_word = ' '.join(slots)
print(new_word)
game()
This seems to work for me:
word = 'EVAPORATE'
wordlist = list(word)
dict = dict(enumerate(wordlist))
slots = list('_' * len(word))
def game():
while '_' in slots:
x = input("Guess the letter: ")
for a,b in dict.items():
if b == x.upper():
slots[a] = x
new_word = ' '.join(slots)
print(new_word)
game()
I have added in a while loop just inside def game(): so that the code will keep running until slots has no underscores left in it. I then moved x = input("Guess the letter: " to inside the while loop so the user can always have another guess until the word is completed.
A few things to add:
Don't you ever use keywords such as list or dict for variables
You have to count the matchs for each letter, example E appears twice, so, you have to count it twice
You have to know when the game ends, because you want to loop the question "guess letter" until the game ends
Add a While loop
Enjoy your game
word = 'EVAPORATE'
wordlist = list(word)
word_length = len(word)
word_dict = dict(enumerate(wordlist))
slots = list('_' * len(word))
def game():
total_letters = word_length
while not game_ended(total_letters):
x = input("Guess the letter: ")
matchs = 0
for pos,letter in word_dict.items():
if letter == x:
matchs += 1
slots[pos] = x
new_word = ' '.join(slots)
total_letters -= matchs
print(new_word)
def game_ended(word_len):
return word_len == 0
game()
just put everything from the input until the end in a while loop
word = 'EVAPORATE'
wordlist = list(word)
# it is not a good idea name a variable the same as a builtin, so change from 'dict' to 'worddict'
worddict = dict(enumerate(wordlist))
slots = list('_' * len(word))
def game(x):
# we also need to change it here
for a,b in worddict.items():
if b == x:
slots[a] = x
new_word = ' '.join(slots)
print(new_word)
while any([i == '_' for i in slots]):
x = input("Guess the letter: ")
game(x)
the while check if any letter in slots is a _, if there is any, keep playing.
note that I also pass the input as a variable to game (it's not necessary, but it's better)

Categories

Resources