How do I parse a string without running into infinite loops? - python

Hello everyone I have a question regarding a parsing of string and this is the code I have so far:
sentence =' '
while sentence != 'q':
sentence = input('Please enter your input: ').split(',')
if len(sentence) > 1:
print('First word: {sentence[0]}')
print('Second word: {sentence[1]}')
continue
elif len(sentence) == 1:
print('Error no comma.')
continue
elif sentence == 'q':
break
And the output will be if there is no comma inputted will give me the following:
Enter input string:
Jill Allen
Error: No comma in string.
and it will keep on asking me for a string until I entered q for quit and the program exits as follows:
Enter input string:
Jill, Allen
First word: Jill
Second word: Allen
Enter input string:
Golden , Monkey
First word: Golden
Second word: Monkey
Enter input string:
Washington,DC
First word: Washington
Second word: DC
Enter input string:
q
My problem is I am unable to quit the infinite loop. Can anyone help me on this? I think the program is unable to distinguish 'Jill Allen' from 'q' since both of them have len(sentence) == 1 and that is the problem as it gives me Error no comma and asked for an input over and over.

I think the key to understanding your problem may be here:
sentence = input('Please enter your input: ').split(',')
You are storing the user input in a string, but then you are calling the string method str.split(). This method basically returns a list of sub-strings, based on the separator you pass as an argument. If there is no separator, the method will instead create a list whose only element is the original input string.
You can find more information about this method here: https://docs.python.org/3/library/stdtypes.html#str.split.
So, if your input is "q", separator will be storing the array ["q"], as there is no comma. And this array's length is 1, so it will enter the first "elif", and execute the "continue", therefore ending current iteration.
In absence of further information about your project, if you need to do it this way, you can change the order of the last two conditionals and the break conditional itself in order for it to work:
sentence =' '
while True:
sentence = input('Please enter your input: ').split(',')
if len(sentence) > 1:
print(f'First word: {sentence[0]}')
print(f'Second word: {sentence[1]}')
continue
elif sentence[0] == 'q':
break
elif len(sentence) == 1:
print('Error no comma.')
continue
I also changed the while condition, because it was redundant with the "break" statement.

You have to change the places of the last two if statements. Because the last if statement never gets executed as if you split sentence which is just q, its length is 1.
sentence =' '
while sentence != 'q':
sentence = input('Please enter your input: ').split(',')
if len(sentence) > 1:
print('First word: {sentence[0]}')
print('Second word: {sentence[1]}')
continue
elif sentence == 'q':
break
elif len(sentence) == 1:
print('Error no comma.')
continue

Check this code. It's working fine for me.
def wordPrinter(text):
if len(sentence) > 1:
print(f'First word: {sentence[0]}')
print(f'Second word: {sentence[1]}')
elif len(sentence) == 1:
print('Error no comma.')
while True:
sentence = input('Please enter your input: ').split(',')
if sentence == ["q"]:
break
else:
wordPrinter(sentence)

As you splitting the input from very beginning you have to compare string by list element.
Code:
sentence =' '
while True:
sentence = input('Please enter your input: ').split(',') #['q']
if len(sentence) > 1:
print(f'First word: {sentence[0]}')
print(f'Second word: {sentence[1]}')
continue
elif sentence == ['q']:
break
else:
print('Error no comma.')
continue

while (sentence := input('Please enter your input: ')) != 'q':
first, *rest = sentence.split(',')
if rest:
print(f'First word: {first}')
second, *rest = rest
print(f'Second word: {second}')
if rest:
print(f'Rest: {",".join(rest)}')
else:
print('Error no comma.')
You can use Python 3.8's walrus operator to assign the input to a variable and also check it's value. I then used iterable unpacking to get the first element of the str.split and the rest as a list. Checking a list itself in a condition tells you if it has any elements in it. I did the same for the second word. Additionally I'm also printing the rest of the words if there are any.

when you use split() you will take list, so sentence cant be str('q')
try like this:
sentence=' '
while True:
sentence = input().split(',')
if (len(sentence) == 1)&(sentence[0] == 'q'):
break
elif len(sentence)<=1:
print('error')
else:
print(f'First word: {sentence[0]}')
print(f'Second word: {sentence[1]}')

Related

How do you insert repeated values with distinct indices into an empty list in python?

I'm trying to build a basic program where the computer selects a word out of a pre-existing list (called "words") and the user must guess the appropriate letters to guess the word. This is what the main function looks like so far:
def game():
word = random.choice(words)
while ' ' or '-' in word:
word = random.choice(words)
if ' ' or '-' not in word:
break
print(f'Hint: The chosen word is {len(word)} letters long')
letters = list(word)
progress = []
while True:
guess = str(input('Guess a letter: '))
if len(guess) > 1:
print('Sorry, guess a single letter: ')
if guess in word:
print(f'The letter {guess} is in the word')
for i, j in enumerate(letters):
if progress.count(guess) >= letters.count(guess):
break
elif j == guess:
progress.insert(i, j)
print('Current progress: ' + '-'.join(progress))
if len(progress) == len(word):
if letters[:] == progress[:]:
print('Congrats! You found the word: ' + str(word))
break
elif guess not in word:
print(f'The letter {guess} is not in the word: Try Again')
continue
My issue is with the for loop where I use enumerate(y) and the respective "elif j == guess" condition. I noticed that when running the function, the code works if the letters that are repeated are successive (ex: in the word "chilly", if I type in "l", the function correctly displays the two l's and the game works as intended). However, if the letters are repeated separately (ex: the word "cologne"), the function doesn't insert the "l" between the two o's, and keeps the two o's together regardless, thus preventing the proper word from ever being guessed. Is there a different method I could use to fix this problem?
You should remember the letters already guessed and simplyfiy the printing to any letter that you remember and use - for any other letter in the word.
Your errror stems from your list and counting method to remember which letters to print or not.
I fixed your incorrect if-condition (see How to test multiple variables against a value? for more on that).
import random
# supply list of words to function to avoid globals
def game(words):
word = random.choice(words)
# fixed your check ... not sure why you do that
while ' ' in word or '-' in word:
word = random.choice(words)
# no break needed, will break if no space/- in
print(f'Hint: The chosen word is {len(word)} letters long')
# remember which letters where guessed already
guesses = set()
while True:
guess = input('Guess a letter: ') # no str needed it is already a str
if len(guess) > 1:
print('Sorry, guess a single letter: ')
continue # back to while loop
# add to guessed letters
guesses.add(guess)
# print message
if guess in word:
print(f'The letter {guess} is in the word')
else:
print(f'The letter {guess} is not in the word: Try Again')
continue # back to while loop
print('Current progress: ', end="")
# assume we have all letters guessed
done = True
for idx, letter in enumerate(word):
if letter in guesses:
# print letter if already guessed
print(letter, end="")
else:
# invalidate assumption and print -
done = False
print("-",end="")
print()
# if assumption not invalidated: done
if done:
print('Congrats! You found the word: ' + str(word))
break
game(["eye", "ear", "egg", "anvil"])
Output:
Hint: The chosen word is 3 letters long
Guess a letter: The letter e is in the word
Current progress: e-e
Guess a letter: The letter r is not in the word: Try Again
Current progress: e-e
Guess a letter: The letter y is in the word
Current progress: eye
Congrats! You found the word: eye

Python: Index Error: sequence subscript is out of range

I am trying to implement a word Chain game; it is a word game where players take turns saying words that start with the last letter of the previous word.
This is my code, and I keep getting an index error on line 9. Can anyone please help. Thanks
This is for Python 3:
x = input('Word: ')
xx = 'sample'
while x and xx:
if x == '':
break
xx = input('Word: ')
if xx == '':
break
while xx[0] != x[-1]:
print('Invalid word')
xx = input('Word: ')
x = input('Word: ')
if x == '':
break
while x[0] != xx[-1]:
print('Invalid word')
x = input('Word: ')
Here is the criteria
Word Chain is word game where players take turns saying words that start with the last letter of the previous word. You might have played this game on long car trips.
Write a program to help you play word chain. Your program should read in words until a blank line is entered. It should print out Invalid word if a word is not a valid play. Your program should work for upper case and lower case words.
​
Notice that the word mandarin is rejected because it doesn't start with the letter e from the previous word: orange. The next word still needs to start with the letter e (from orange), rather than n (from the end of the invalid word, mandarin).
Here is another example:
Word: tomato
Word: okra
Word: asparagus
Word: seaweed
Word: cake
Invalid word
Word: dried apricots
Word: cake
Invalid word
Word:
​
Here's one last example. Don't forget it should work regardless of case!
Word: Australia
Word: Antartic
Word: Canada
Word: England
Invalid word
Word: Denmark
Invalid word
Word:
​
You will always read in at least two words.
Please help if you can thank you
You can simply include your condition in the while loop and simply your whole code like the following:
word = "elaborate"
old_word = 'sample'
while word != '' and old_word != '':
old_word = word
word = input('Word: ')
if word[0].upper() != old_word[-1].upper():
print('Invalid word')
word = input('Word: ')
This should work, check the comments in the code! You would need to check if the word you have entered is of length > 1, and also keep track of the last good word!
old_word = 'sample'
word = input('Start the chain game, the first word is sample: ')
last_good_word = word
invalid_flag = False
#While the word is not empty
while word != '':
#If the last word was invalid, use the last good word, else get the latest word
if invalid_flag:
old_word = last_good_word
else:
old_word = word
#We get the new word
word = input('Enter the next word: ')
#Check if the new word is not a blank string
if len(word) > 1:
#If word chain is not met, tell that it is invalid, and set the invalid flag to True
if word[0].upper() != old_word[-1].upper():
print('Invalid word')
invalid_flag = True
last_good_word = old_word
#Else set the invalid flag to False
else:
invalid_flag = False
Outputs will look like
Start the chain game, the first word is sample: echo
Enter the next word: open
Enter the next word: note
Enter the next word: even
Enter the next word:
Start the chain game, the first word is sample: echo
Enter the next word: open
Enter the next word: yellow
Invalid word
Enter the next word: mellow
Invalid word
Enter the next word: note
Enter the next word: even
Enter the next word: yellow
Invalid word
Enter the next word: mellow
Invalid word
Enter the next word: never
Enter the next word: river
Enter the next word:

Word list storage returning "string index out of range". Why?

I am working on an assignment where we have to ask the user for a word, and then if the word has a letter that repeats the initial letter in the word, such as: ApplesAuce (the A repeats), the program will store the word in the list and then print out the list when the user is done entering words.
I am getting this error
if word[0].lower() in word[1:].lower(): IndexError: string index out
of range
Here is my code:
wordlist = []
word = input("Please enter a hilariously long word: ")
# I said "hilariously long" to increase the likelihood of a repeat letter
while wordlist != '':
word = input("Please enter another hilariously long word: ")
if word[0].lower() in word[1:].lower():
wordlist.append(word)
word = input("Please enter another hilariously long word: ")
print("All of the words that had repeated first letters are: ")
print(wordlist)
Test for the presence of a word and break out of the while loop if it isn't there.
wordlist = []
msg = "Please enter a hilariously long word: "
# I said "hilariously long" to increase the likelihood of a repeat letter
while True:
word = input(msg)
if word:
if word[0].lower() in word[1:].lower():
wordlist.append(word)
else:
break
print("All of the words that had repeated first letters are: ")
print(wordlist)
Note also that wordlist is a list so the test while wordlist != "" will always be the case because a list is not a string
This should work.I have introduced the breaker that is quit or done will break the loop. I have also moved your first input inside which will add another if wordlist is populated.
wordlist = []
# I said "hilariously long" to increase the likelihood of a repeat letter
while 1:
word = input("Please enter {}hilariously long word: ".format('another ' if wordlist else ''))
# get out if done or quit is typed
if word in ('done','quit'):
break
if word[0].lower() in word[1:].lower():
wordlist.append(word)
print("All of the words that had repeated first letters are: ")
print(wordlist)

Editing a String without Python Commands (with "for i in range")

For an assignment, I need code that asks the user for a word and a letter. Then, it edits the word to not include the specific letter. It needs in include a "for i in range" statement. The code before works but doesn't use a for loop and uses a python command.
word1 = raw_input ("Give me a word! ")
letter1 = raw_input ("Give me a letter! ")
modify = word1.replace(letter1,"")
check = word1.find(letter1)
if check == -1:
print "There is no letters to replace in", word1
check = 0
if check >= 1:
print modify
How about:
word = raw_input('Give me a word! ')
letter = raw_input('Give me a letter! ')
cleaned = ''
for i in range(len(word)):
if word[i] != letter:
cleaned += word[i]
if cleaned:
print cleaned
else:
print 'There is no letters to replace in', word
You can iterate through a string letter by letter like you would a list or dict
word='someword'
for letter in word:
print(letter)

how to only allow letters to be used python statment

I'm making a Morse code program:
def main ():
morse_code = {"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":"--.."}
phrase = input("please enter your word or words: ")
for key in phrase:
print("your word or sentence translated to morse code is : ")
print(morse_code[key], end = " ")
if phrase == int or float:
print("try the input")
retry()
def retry ():
main()
retry()
main()
How do I print an error if someone enters a number?
This is what you need:-
morse_code = {"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":"--.."}
phrase = input("please enter your word or words: ")
if any(char.isdigit() for char in phrase):
print("try the input")
else:
print("your word or sentence translated to morse code is : ")
code = ' '.join(morse_code[key] for key in phrase)
print(code)
You can use str.isdigit
for key in phrase:
if not key.isdigit():
print("your word or sentence translated to morse code is : ")
print(morse_code[key], end = " ")
You can check if the input is between a and z by doing:
try:
index = ord(key.lower())
if index >= 97 and index <= 122:
# Do your thing
except TypeError:
# Wrong input
The TypeError shouldn't happen, it's just good practice to wrap code with errors handling.
Or, you can do:
if not key.isdigit():
# Key isn't between 0 and 9. Can be uppercase or a symbol, though.
if ord(key.lower()) >= 97 and ord(key.lower()) <= 122:
# Do your thing. It's pretty much the same as before but with one more step.
Your first problem you will have is that the if statement is A: after the printing out of the Morsecode version of the letter, and B: it is outside of the for loop completely.
You can rectify this by putting it in the for loop before the printing like so:
phrase = input("please enter your word or words: ")
print("your word or sentence translated to morse code is : ")
for key in phrase:
if phrase == int or float:
print("try the input")
else:
print(morse_code[key], end = " ")
However the above code still won't work, as the way you are checking if the current letter being printed out is a int or float isn't how you do it.
The easiest method is to change the codition of the if statement to if key.isdigit():
This will leave you with this final block of code:
phrase = input("please enter your word or words: ")
print("your word or sentence translated to morse code is : ")
for key in phrase:
if key.isdigit:
print("try the input")
else:
print(morse_code[key], end = " ")
This now works, however, lets say I enter abc123. The output I would get is .-
-...
-.-.
try the input
try the input
as the code is running the forloop regardless of if there are numbers in the input or not. To prevent this, you should check the input for numbers, before you have the for loop printing out the morse code.
phrase = input("please enter your word or words: ")
while not phrase.isalpha():
phrase = input("invalid input: ")
print("your word or sentence translated to morse code is : ")
for key in phrase:
print(morse_code[key], end = " ")
If you need any help, let me know!
Using isdigit() will solve your problem also use break to receive new input
morse_code = {"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":"--.."}
Morse_Parse=[]
phrase = input("please enter your word or words: ")
print("your word or sentence translated to morse code is : ")
for key in range(0,len( phrase)):
if phrase[key].isdigit():
print("you inderted an digit , Try another input")
break
else:
Morse_Parse.append(morse_code[phrase[key]]+" ")
print("Morse for your input is "Morse_Parse)
using flag will improve print task
morse_code = {"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":"--.."}
Morse_Parse=[]
phrase = input("please enter your word or words: ")
print("your word or sentence translated to morse code is : ")
flag=1
for key in range(0,len( phrase)):
if phrase[key].isdigit():
print("you inderted an digit , Try another input")
flag=0
break
else:
Morse_Parse.append(morse_code[phrase[key]]+" ")
if flag==1:
print("Morse for your input is "Morse_Parse)
how to only allow letters
How do I print an error if someone enters a number?
The second case is covered easily by checking .isdigit on each character as others mentioned. But I will cover the first case.
Start by defining a string of valid characters. Assuming your valid character set is lowercase a-z, this would be the same as string.ascii_lowercase
import string
valid_characters = string.ascii_lowercase # a-z
def char_valid(c):
'''Check if a character is valid, returns True/False'''
return c in valid_characters
def phrase_valid(phrase):
'''Check if the phrase is valid, returns True/False'''
return all(char_valid(char) for char in phrase)
while True:
user_phrase = input('Enter some characters')
if phrase_valid(user_phrase):
# If the phrase is valid, end the loop
break
else:
print('That was not a valid phrase')
# the loop continues and will ask for input again
This pattern works any time you want to keep asking for input until it is valid.

Categories