comparison within loop while maintaining value - python

I am trying to make a python program that
1. compares the first and last letter of a word
2. tell whether the words inputted to the program are in alphabetical order
e.g.) alaska baobab cadillac => would pass
e.g.) alaska baobab greg => would not pass
my code is shown below
num_words = int(input())
while num_words > 0:
my_word = str(input())
num_words -= 1
alphabet_order = ord(my_word[0].lower())
if my_word[0].lower() != my_word[-1].lower() or alphabet_order != ord(my_word[0].lower()):
print(my_word)
break
alphabet_order += 1
if alphabet_order == ord('z') + 1:
alphabet_order = ord('a')
else:
print('no mistake')
Hi everyone on stack.
I am pretty new to programming and I am starting to find assigning variables within a loop very cumbersome.
It seems like my variable alphabet_order keeps getting renewed every time when the loop takes in a new input.
What would be a great way to steadily increase the alphabet_order variable by 1 while only renewing ord(my_word[0]) every loop?

Few notes, while loops are good for when you don't know how many times you are going to loop. for loops are good for when you know how many items you are looping. In this case we have a known number of words we are to check so using a for loop makes more sense. This way we don't need to take an input on telling us how many words we expect.
Also your code wasn't dealing with the words you were dealing with the sentence, so instead you should split() your input by the space to get a list of the words to operate on. for loops can iterate through a list which is useful for us.
Note that for loops also can take an else, the else section runs after the for loop is finished all the elements it's iterating through and we know that if the for is finish all the words in the list, then the else section will kick in. If we break out, then the else doesn't run.
The rest you more or less had it, just need a starting ord('a') would have made life easier.
my_word = input() #take a sentence such as alaska baobab cadillac
current_ord = ord('a')
for each in my_word.split(' '):
if each[0].lower() != each[-1].lower() or current_ord != ord(each[0].lower()):
print(f"bad word {each}")
break
current_ord += 1
if current_ord == ord('z') + 1:
current_ord = ord('a')
else:
print('no mistake')

Maybe this is helpful to you. Instead of initializing it inside the loop, declare it outside the loop and assign it differently based on the conditions.
Tip: having while num_words > 0 is redundant because it will terminate automatically when it hits 0 as it is treated as False. And there is no need to convert int to a str type as it is str by default.
num_words = int(input("Enter a number"))
alphabet_order = None
while num_words:
my_word = input("Enter a word")
num_words -= 1
if alphabet_order is None: # happens only once
alphabet_order = ord(my_word[0].lower())
if ord(my_word[0].lower()) >= alphabet_order:
print('ok')
alphabet_order = ord(my_word[0].lower()) # update alphabet_order
else:
print('not ok EXITING')
break # closing loop

Related

SNHU Python 'Simon Says': compare two strings for equality character-wise, without using an index?

I was given a prompt to solve and was able to write code that passed, but my question is, is there a more simplified way I could write this without having to create a new named variable (s_index = 0)? The code works just fine but I'm not sure if I solved it the way I was expected to and am open to suggestions for improvement :)
Please note that this section in the work book has us focusing on using continue and break within loops
"Simon Says" is a memory game where "Simon" outputs a sequence of 10 characters (R, G, B, Y)
and the user must repeat the sequence. Create a for loop that compares the two strings.
For each match, add one point to user_score. Upon a mismatch, end the game.
Sample output with inputs: 'RRGBRYYBGY' 'RRGBBRYBGY'
User score: 4
user_score = 0
simon_pattern = input()
user_pattern = input()
s_index = 0
for letter in user_pattern:
if letter == simon_pattern[s_index]:
user_score += 1
s_index += 1
else:
break
print('User score:', user_score)
using functions to encapsulate small specific parts of your logic is often helpful
def do_score(user_pattern="1234",simon_pattern="1235"):
# using enumerate you can get the indices
for s_index,a_char in enumerate(simon_pattern):
if s_index >= len(user_pattern) or a_char != user_pattern[s_index]:
# the index should always match the "sum" so no need to track or compute the sum
return s_index
return len(simon_pattern)
this method takes 2 strings and "scores" them based on the "simon_pattern" returning the score
then just
print(do_score(user_entered_input,simon_pattern))
I will rewrite this to this way: (this way you can completely eliminate the variable index, and simon_pattern[index] to get the letter)
Note - in Python a word is just a sequence of character/letters, you can iterate it directly, no need to use index.
simon = 'RRGBRYYBGY'
user = 'RRGBBRYBGY' # User score: 4
user_score = 0
for user_char, simon_char in zip(user, simon):
if user_char == simon_char: # continue to check/and match...
user_score += 1
else: # break, if no match!
break
print('User score:', user_score)
Strictly, you never need to know the index or index into the strings, you can just use zip() to combine tuples of respective characters from the two (possibly different-length) strings:
def do_score(user_pattern='RRGBRYYBGY', simon_pattern='RRGBBRYBGY'):
score = 0
for uc,sc in zip(user_pattern, simon_pattern):
if uc == sc:
score += 1
else:
break
return score
assert do_score('', '') == 0
assert do_score('RRG', '') == 0
assert do_score('', 'RRG') == 0
assert do_score('RRG', 'RRGB') == 3

Tried to make wordle clone ,doesn't work can you figure out what I did wrong

I was creating a wordle clone but when I enter word it doesn't do anything, help
so how it works is that there is only 29 possible words and the game is suppose to tell you how many of the letters in the code are in the actual wordle.
import random
words=['about','block','chair','dream','eagle','faint','great','homes','ideas','joker','karen','latin','mouth','noise','orion','paint','queen','raven','speed','smart','tooth','truck','unite','venom','venus','where','xerox','youth','zebra']
wordlenum=random.randint(0,28)
wordle=words.pop(wordlenum)
letters1=''
for char1 in wordle:
letters1 += char1
letters2=''
correct=0
while True:
guess=input('guess:')
for char2 in guess:
letters2+=char2
for l1 in letters1:
for l2 in letters2:
if l1==l2:
correct+=1
if correct == 5:
print('you win')
break
else:
print(correct)
You have extra for loops in your code,
for l1 in letters1:
for l2 in letters2:
this part of code will execute 25 times, and will match if any of the letters in both words are same.
Hence give false results,
For this you can use zip method.
Also, After the failed attempt, you need to reset the correct counter and the word also needs to be reset, otherwise it is keep adding on top of the that.
Also, you would not require to explicitly add the words again to a new variable.
This
letters1=''
for char1 in wordle:
letters1 += char1
and
for char2 in guess:
letters2+=char2
are unnecessary.
After modification, here you can use.
import random
words=['about','block','chair','dream','eagle','faint','great','homes','ideas','joker','karen','latin','mouth','noise','orion','paint','queen','raven','speed','smart','tooth','truck','unite','venom','venus','where','xerox','youth','zebra']
wordlenum=random.randint(0,28)
wordle=words.pop(wordlenum)
while True:
correct = 0
guess=input('guess:')
# you can put some validations here on guess, like len(guess) == 5 and only chars
for l1, l2 in zip(wordle, guess):
if l1==l2:
correct+=1
if correct == 5:
print('you win')
break
else:
print(correct)
Hope this helps.
If you want to find out how many letters from one string occur in another string then convert the strings to sets and find the length of their intersection. For example:
s1 = 'chair'
s2 = 'train'
print(len(set.intersection(set(s1), set(s2))))
Output:
3

While-loop within a while-loop python

I am trying to write a while-loop within a while-loop, and for some reason it is not working as it should. I know I'm probably missing something really trivial here, but I just don't understand how its not working!
The purpose of the loop is to compare two strings to see whether or not they contain any 3 consecutive words the same. I first split the two strings into lists of their respective 3 word string combinations which I store in the lists strings and stringscompare. Then I loop through each 3 word string in stringscompare for each 3 word string in strings.
This will probably seem like a pretty long way round for some but I am only a novice programmer, any improvements would be greatly appreciated.
So currently, the second while loop runs all the way through, however the first one only loops through once, for the first string in strings. If the string matches I would like it to break from both loops, however these loops are also in a much bigger for loop which I don't want it to break out of.
e.g.
'this is a string'
'this is another string' --no match
'this is a list a strings' -- matches 'this is a'
'the list is a string' -- should match 'is a string' but currently does not
strings = <list of 3 word strings> [...,...,...]
stringscompare = <list of 3 word strings to compare>
v=0, x=0
while v < len(strings) and stop == False:
while x < len(stringscompare) and stop == False:
if re.search(strings[v], stringscompare[x]):
same.append(dict)
stop = True
x += 1
v +=1
You never reset x inside the outer loop. As a result it'll always be equal or greater to len(stringscompare) after the first iteration of the outer loop.
Set it to 0 in the outer loop:
v = 0
while v < len(strings) and stop == False:
x = 0
while x < len(stringscompare) and stop == False:
Other observations:
Don't use stop == False where not stop will do.
You could just use a for loop, then break out twice:
for s in strings:
for sc in stringscompare:
if re.search(s, sc):
same.append(dict)
break
else:
continue
# only reached if the inner loop broke out
break
or use any() with a generator expression to find the first match:
if any(re.search(s, sc) for s in strings for sc in stringscompare):
same.append(dict)
you use twice the same variable stop I think you should set the stop to false after the loop:
strings = <list of 3 word strings> [...,...,...]
stringscompare = <list of 3 word strings to compare>
v=0, x=0
while v < len(strings) and stop == False:
while x < len(stringscompare) and stop == False:
if re.search(strings[v], stringscompare[x]):
same.append(dict)
stop = True
x += 1
stop = False
v +=1
I would suggest something like this..
strings = [] # <list of 3 word strings> [...,...,...]
stringscompare = [] # <list of 3 word strings to compare>
stop = False
for x in strings:
if stop:
break
for v in stringscompare:
if re.search(v, x):
stop = True
break
A for loop seems a lot more appropriate here. Is this what you're trying to achieve?
Well the most obvious problem with the code here is that you do not set the value of X to be 0 again once the inner loop finishes. I'll explain:
Lets say both 'strings' and 'stringscompare' length is 3. When you first enter the big while loop, v=0 and x=0.
When we enter the second loop, x=0. When we leave the second loop, if no match was found, x = length(stringscompare) = 3.
Now, when we go back to the first while loop it DOES actually go inside the loop again - but it does nothing, as the clause for the 2nd loop cannot be satisfied - X is still 3!
You can fix this by resetting X at the end of loop 2:
strings = <list of 3 word strings> [...,...,...]
stringscompare = <list of 3 word strings to compare>
v=0, x=0
while v < len(strings) and stop == False:
while x < len(stringscompare) and stop == False:
if re.search(strings[v], stringscompare[x]):
same.append(dict)
stop = True
x += 1
x = 0 #resetting X
v +=1
You can easily track downs problems like this one by debugging. There are many methods to debugging, its an art really :P
What I would recommend for you:
If your'e using Eclipse, PyCharm, etc, you can use the built in debuggers which are amazing. You can stop at any point of the program by adding breakpoints, see the value of all the variables, etc.
For example, in this case, I would put a breakpoint on the first loop statement ('while v < len...'). That way, you couldv easly see that the first loop is in fact running, and its the second loop thats the problem.
Printing is your friend. Something simple like this for example:
v=0, x=0
while v < len(strings) and stop == False:
print "About to enter second loop..."
while x < len(stringscompare) and stop == False:
if re.search(strings[v], stringscompare[x]):
same.append(dict)
stop = True
x += 1
v +=1
You could also print the values of variables btw.
There are many other ways to do what you're trying to do (triangle graphs, advanced search methods, maybe a more complex data structure, etc). But for now - I think the best thing for you is to solve problems in the most straightforward way you can - focus on writing quality code (well named variables, indents, comments etc). The geeky, 'top performance' cutting edge tricks will come in later :)
Good luck and have fun!

python help! If/else statement

I have been learning python through code academy. It asked me to create a if else statement that prints the users input, but if there is no input print "empty". I did pass the tutorial but when there is a user input it prints both the users input and "empty".
here is my code:
print "Welcome to the English to Pig Latin translator!"
original = raw_input("what is your name?")
length = len("original")
if length > 0:
print original
else: length < 0
print "empty"
Notice that print under else is not indented. I thought you had to indented it, but when i do it gives me an error.
You seem to have a couple issues with your code. First I believe you should change your assignment of length to:
length = len(original)
That way you get the correct length of the string you binded to the name original. If you use len("original"), you will pass the string "original" to the len() function, and it will just count the characters in that string. Regardless of what the user of your program inputted, your length will always be 8, since that's how many characters are in the string "original"
Also keep in mind that the len() function will never return a negative value. So testing if length < 0 doesn't make sense. You probably wanted to test if it equals 0. It seems as if you were trying to use an elif statement.
Try:
print "Welcome to the English to Pig Latin translator!"
original = raw_input("what is your name?")
length = len(original)
if length > 0:
print original
elif length == 0:
print "empty"
elif statements let you test conditions just like if statements. elif is short for "else if".
Furthermore, as #chepner pointed out in the comments, there is no need to even test the second condition at all. You can just as easily go with:
else:
print "empty"
The else syntax is not followed by any condition. It automatically enters the indented block of code if the other conditions evaluate to False.
Was the length < 0 intended to be a comment? You need the comment character #.
else: # length < 0
print "empty"
It's wrong anyway, it should be length <= 0.
Without a comment character it was being interpreted as the statement to use as the else clause. It didn't create an error since length < 0 just generates a boolean result that you didn't do anything with, but it prevented you from having another statement as part of the else.
else: length < 0
print "empty"
should be
elif length == 0:
print "empty"
Python has significant whitespace, things that are indented the same are in the same scope.
First off, it is not len("original") it is len(original). If you use quotes you are making it a constant value, "original", rather than a variable named original.
Second, instead of checking the length of the string you should use this
if original:
# Type here what happens if the string is not empty
else:
# Here what happens if the string is empty
By Python standard any collection, including strings, equals false if it is empty(aka contains no elements) and true if it contains any elements.
There is a a statement after else.
else: length < 0
print "empty"
Maybe you are looking for an (elif is another way to check another condition after the if if the previous if fails.)
elif length <= 0:
or just a plain
else:
print "empty"
it will never go past zero anyways you could have a == conditional for zero and it would work.
elif length == 0:
this is probably the best way there is no need to check another condition.
if length > 0:
print original
else:
print "empty"
also just a side note length = len("original")
there is not suppose to be quotation marks around original because its a variable :). You will just be getting the string "original" not the actual stuff inside of the variable.
The end result ..
print "Welcome to the English to Pig Latin translator!"
original = raw_input("what is your name?")
length = len(original)
if length > 0:
print original
else:
print "empty"
To check if there is an item in a list, simply do this:
if List_name:
{code here}
...
So, your code should very simply look like this:
print "Welcome to the English to Pig Latin translator!"
original = raw_input("what is your name?")
if original:
print original
else:
print "Empty"
It's that easy :D

python secret word program

I'm trying to write a program where the user has to guess a letter in the goal of unlocking the secret word. If the secret word is guessed correctly before the maximum 8 guesses, the function returns true else the function returns false. For some reason my function just doesn't produce the right output. I would enter the letter 'a' and it would print "Letters guessed so far: ['a']" and then the program would end. I need help in fixing this issue.
secretWord = 'hello'
lettersGuessed = []
def isWordGuessed(secretWord,lettersGuessed):
guess = 0
while guess <= 8:
secretLetters = list(secretWord)
secretWordLen = len(secretLetters)
letter = input('Enter a letter: ')
lettersGuessed.append(letter)
print('Letters guessed so far: ',lettersGuessed)
if letter not in secretLetters:
guess += 1
while letter in secretLetters:
secretLetters.remove(letter)
if secretLetters == []:
return True
else:
return False
isWordGuessed(secretWord,lettersGuessed)
Your first problem is, as kwatford explained, that you are returning every time through the loop. You can fix that by moving the if statement outside the while loop.
Your next problem, as Vorticity explained, is that it will never return early, even if the user guesses the whole word. To fix that, move the if part back inside the loop, but leave the else part outside the loop (meaning you no longer need the else)
After that, it still won't work, because you're doing secretLetters = list(secretWord) each time through the loop, so you can only win if you guess all the letters in one guess (which is impossible, unless the word is, say, "a" or "aaaaa"). To fix that, move that line outside the loop.
Putting it all together:
def isWordGuessed(secretWord,lettersGuessed):
guess = 0
secretLetters = list(secretWord)
while guess <= 8:
secretWordLen = len(secretLetters)
letter = input('Enter a letter: ')
lettersGuessed.append(letter)
print('Letters guessed so far: ',lettersGuessed)
if letter not in secretLetters:
guess += 1
while letter in secretLetters:
secretLetters.remove(letter)
if secretLetters == []:
return True
return False
As a side note, there are a lot of things you can do to simplify this.
First, you really just need a set of all letters in the secret word—you don't need to know the order, or how many copies there are of each, etc. So, instead of a list, use a set. This also means you don't need the loop around secretLetters.remove(letter).
More trivially, you create secretWordLen but never use it.
You also accept and append to a lettersGuessed passed in by the caller, but the caller is just passing you an empty list, and never using it after the fact, so why bother? And if you don't need to mutate it for the caller's benefit, you can just keep it as a string, so the user sees help instead of ['h', 'e', 'l', 'p'], which is a lot nicer.
You've also got a few cases that are being tested even when they can't possibly be true.
Finally, an empty list (or set, or any other sequence) is false, so there's no reason to explicitly compare to the empty list.
While I'm at it, I'm going to PEP8-ify the spacing to make it easier to see the indentation.
So:
def isWordGuessed(secretWord):
guess = 0
lettersGuessed = ''
secretLetters = set(secretWord)
while guess <= 8:
letter = input('Enter a letter: ')
lettersGuessed += letter
print('Letters guessed so far:', lettersGuessed)
if letter not in secretLetters:
guess += 1
else:
secretLetters.remove(letter)
if not secretLetters:
return True
return False
The last if statement is indented too far, causing it to be part of your while loop. Since both branches of the condition cause the function to return, it always returns on the first iteration of the loop.
You just need to move your return for the False case. Basically, the way your code is written right now, you will never go back to the beginning of your loop. Also, as noted by abarnert, you will never exit the loop because you are reinitializing secretLetters every time you loop. You have to initialize it outside the loop. Your code should look like this:
secretWord = 'hello'
lettersGuessed = []
def isWordGuessed(secretWord,lettersGuessed):
guess = 0
secretLetters = list(secretWord)
secretWordLen = len(secretLetters)
while guess <= 8:
letter = input('Enter a letter: ')
lettersGuessed.append(letter)
print('Letters guessed so far: ',lettersGuessed)
if letter not in secretLetters:
guess += 1
while letter in secretLetters:
secretLetters.remove(letter)
if secretLetters == []:
#Return true if all correct letters have been guessed
return True
#Return false if guessed incorrectly eight times
return False

Categories