I'm new to python 3 and I feel like I am learning in the worst way possible. Everything is through an online text-book called zybooks. I've been trying to understand for loops, and for the program I am supposed to write I have to use for loops.
here are the instructions: "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. Ex: The following patterns yield a user_score of 4:
simonPattern: R, R, G, B, R, Y, Y, B, G, Y
userPattern: R, R, G, B, B, R, Y, B, G, Y
to start I am given this:
user_score = 0
simon_pattern = 'RRGBRYYBGY'
user_pattern = 'RRGBBRYBGY'
print('User score:', user_score)
I have passed the first "test" with this code:
user_score = 0
simon_pattern = 'RRGBRYYBGY'
user_pattern = 'RRGBBRYBGY'
for simon_pattern in str(simon_pattern):
for user_pattern in str(user_pattern):
if str(simon_pattern) == str(user_pattern):
user_score += 1
continue
if str(simon_pattern) != str(user_pattern):
break
print('User score:', user_score)
the problem is when it goes to do the second test my output is still User score: 4 instead of User score: 7 (the strings for simon_pattern and user_pattern change for the second test.)
I know I need to compare each element in the string to each other one at a time and add +1, and as soon as two elements don't match my loop needs to stop. I have tried:
user_score = 0
simon_pattern = 'RRGBRYYBGY'
user_pattern = 'RRGBBRYBGY'
for s in simon_pattern:
for u in user_pattern:
if simon_pattern [0] == user_pattern [0]:
user_score += 1
if simon_pattern [0] != user_pattern [0]:
break
if simon_pattern [1] == user_pattern [1]:
user_score += 1
if simon_pattern [1] != user_pattern [1]:
break
(and then I continue the above loops until I get to [9] and print the user_score, but that doesn't work, either.)
I've tried comparing len(simon_pattern) to len(user_pattern) but that just throws back an error telling me that it can't perform that function because I have strings and not integers.
I'm wondering if someone can tell me what I'm doing wrong or point me in the right direction. Because at this point I don't know what I'm doing wrong and why. I'm sorry this is really long, but I wanted to explain as thoroughly as I could. Thank you for your help.
You'd have a much easier time using an index :
user_score = 0
simon_pattern = 'RRGBRYYBGY'
user_pattern = 'RRGBBRYBGY'
for i in range(len(simon_pattern)):
if user_pattern[i] == simon_pattern[i]:
user_score += 1
The issue with your second attempt code (for s in simon_pattern ...) is that you were comparing every s in simon_pattern to every u in user_pattern). You need to correlate these (usually with an index) so that you only compare the first to the first, second to the second etc.
Using index to iterate through each loop you need some number that increases as you go through each iteration. you can just use user_score since it is already assigned to 0, and going to increase after each iteration by 1. You will probably say "but it is going to be increased only if there is a match!" (this is right)! but if there is mismatch you are going to break out of the loop anyways, and end the game so this it's a perfect.
user_score = 0
simon_pattern = input()
user_pattern = input()
for i in simon_pattern:
if user_pattern[user_score] == simon_pattern[user_score]:
user_score += 1
else:
break
print('User score:', user_score)
user_score = 0
simon_pattern = input()
user_pattern = input()
for i in range(len(simon_pattern)): # loop for each letter in simon_pattern
if user_pattern[i] == simon_pattern[i]: # if user matches simon
user_score += 1 # add 1 to the user_score
else: # otherwise exit the game
break
print('User score:', user_score) #output final score
If you need to do it with continues and breaks like I had to, it would be something like this:
user_score = 0
simon_pattern = input()
user_pattern = input()
for i in range(len(simon_pattern)):
if user_pattern[i] == simon_pattern[i]:
user_score += 1
continue
else:
break
print('User score:', user_score)
user_score = 0
simon_pattern = input()
user_pattern = input()
x = 0
for n in simon_pattern:
if n == user_pattern[x]:
x += 1
user_score += 1
else:
break
print(f'User score: {user_score}')
the "most useful" answer above is missing the break which will cause the tests to fail. Use the code below to pass all the tests. As many people suggested, using an index is your best bet and gives you the cleanest code as well.
user_score = 0
simon_pattern = input()
user_pattern = input()
for i in range(len(simon_pattern)):
if user_pattern[i] == simon_pattern[i]:
user_score += 1
else:
break
print('User score:', user_score)
Related
I am brand new to coding and working my way through an intro class via Zybooks. This challenge activity is asking me to add one point to user_score for every letter that is a match and break the loop when there is a mismatch. Simon_pattern and user_pattern are both input. This is the code I have so far:
user_score = 0
simon_pattern = input()
user_pattern = input()
for character in simon_pattern:
for input in user_pattern:
if input == character:
user_score += 1
continue
if input != character:
break
print('User score:', user_score)
The code works, but the returned value is wrong. Given simon_pattern ='RRGBRYYBGY'and user_pattern = 'RRGBBRYBGY' the output should be User Score: 4, but my User Score is coming out as 3.
I'm not quite sure what part of my code needs fixing and unfortunately zybooks does not give you any hints. Thanks in advance for the help of this awesome community!!
Hi and welcome to coding! A few notes: Notice how the input() function is used to gather input from the user? Because of this, it is considered a keyword and it is bad practice to name your variables input, because it will overwrite the reference to the function.
Now considering your problem. Instead of a nested loop I would use a single for lop and check the characters at each index within both strings. If they match, add a point. Otherwise, break the loop. You also want to stop the loop if it goes beyond the number of characters in either pattern. One trick for that is to find the minimum length between both patterns. The min function is useful for this.
user_score = 0
simon_pattern = input()
user_pattern = input()
length = min(len(simon_pattern), len(user_pattern))
for i in range(length):
if user_pattern[i] == simon_pattern[i]:
user_score += 1
else:
break
print('User score:', user_score)
This should work :
user_score = 0
simon_pattern = input()
user_pattern = input()
for simon_character, user_character in zip(simon_pattern, user_pattern):
if simon_character == user_character:
user_score += 1
else:
break
print('User score:', user_score)
Be careful not to redefine the Python keywords such as input or print for example. The rest of your program could be modified if you need to reuse these functions
So after finishing the code, I would like to have an option where the user would like to try again by typing Y/n or N/n. How do I make it?
a=int(input('enter value of n: '))
i = 1
sum=0
while a < 1 or a > 300:
print(a, 'is not in the range 1-300')
exit()
for a in range(1,a+1):
print (a, end = ' ')
while i<=a:
if i%3==0 or i%5==0:
sum=sum+i
i=i+1
print('\nsum of all multiples of 3 and 5 is:',sum)
repeat=str(input('Would you like to try again? Y/N?'))
Here's a simple way to do it (keeping your code structure) without any functions or jargon (for beginners :]):
from sys import exit # Just something to exit your code
repeat = 'y' # So it starts the first time
while repeat.lower() == 'y': # repeat.lower() -> convert the string 'repeat' to lowercase, incase user inputs 'Y'. you could also use the or keyword here though
n = int(input("Enter value of n:\n>>> "))
if n < 1 or n > 300:
print("'n' must be between 1 - 300, not " + n) # You could use f-strings, check them out!
exit()
sum_of_multiples = 0
# I'm combining your for and while loop as shown below
for i in range(1, n + 1): # Don't name your 'i' and 'n' variables the same -> you did so with 'a'
print(i, end=', ') # There are cleaner ways to do this but I'm assuming this is what you want
if i % 3 == 0 or i % 5 == 0:
sum_of_multiples += i
# Printing output
print(f"\nSum of all multiples of 3 and 5 is: {sum_of_multiples}") # This is called an f-string
repeat = input("\nDo you want to go again?\n>>> ") # If you don't input Y/y, the outer while loop will break and terminate
print("Thank you for running me!") # Prints after the program finishes running
Note that you don't need the exit() when checking if n is within 1 - 300, you could also just use break.
EDIT (WITH BREAK)
Program without from sys import exit below:
repeat = 'y' # So it starts the first time
while repeat.lower() == 'y': # repeat.lower() -> convert the string 'repeat' to lowercase, incase user inputs 'Y'. you could also use the or keyword here though
n = int(input("Enter value of n:\n>>> "))
if n < 1 or n > 300:
print("'n' must be between 1 - 300, not " + n) # You could use f-strings, check them out!
break # This will mean that "Thank you for running me!" gets printed even if your input is wrong
sum_of_multiples = 0
# I'm combining your for and while loop as shown below
for i in range(1, n + 1): # Don't name your 'i' and 'n' variables the same -> you did so with 'a'
print(i, end=', ') # There are cleaner ways to do this but I'm assuming this is what you want
if i % 3 == 0 or i % 5 == 0:
sum_of_multiples += i
# Printing output
print(f"\nSum of all multiples of 3 and 5 is: {sum_of_multiples}") # This is called an f-string
repeat = input("\nDo you want to go again?\n>>> ") # If you don't input Y/y, the outer while loop will break and terminate
print("Thank you for running me!") # Prints after the program finishes running
Hope this helped!
'''
Program that reads first user string input as simon pattern
then reads second user string input as user pattern.
Each character existing in the two strings is compared left to right.
For each equal character the user score is increased by 1.
The loop terminates and outputs user score upon reaching the first
character that doesn't match.
'''
user_score = 0
simon_pattern = input() #input for initial string
user_pattern = input() #best attempt at copying simon_pattern
for i in user_pattern:
for j in simon_pattern:
if i == j:
user_score += 1 #adds 1 to user_score for each equal
#character in the same index for both strings
else:
break #if two characters do not match then end the loop
print('User score:', user_score)
For some reason the output is not what I would expect when I run this program though there are no syntax errors that I can find. Am I using for loops or break in a way that is producing an inaccurate result?
For example if I input: 'RRGBRYYBGY' 'RRGBBRYBGY' the output is 'User score: 6' when the fifth character in each string clearly doesn't match and the output should be 'User score: 4'.
Thanks for any help in advance!!
Your case needs to iterate through simon_pattern and user_pattern side by side, not nestedly. What you need is zip():
user_score = 0
simon_pattern = input() #input for initial string
user_pattern = input() #best attempt at copying simon_pattern
for i,j in zip(user_pattern,simon_pattern):
if i == j:
user_score += 1 #adds 1 to user_score for each equal
#character in the same index for both strings
else:
break #if two characters do not match then end the loop
print('User score:', user_score)
There is already an answer but i will explain The problem with your approach is how your nested loop works, if there are 2 strings "ABCD" and "ABDC"
You are basically taking A from first string match it with A in second string, then you take B in first string match with A in second string; so basically all comparison for characters in first string happen with first character of second string.
Hope this helps :)
Here's another way that doesn't use zip() (requested in the comments):
user_score = 0
simon_pattern = input() #input for initial string
user_pattern = input() #best attempt at copying simon_pattern
letters = min(len(simon_pattern),len(user_pattern))-1 # Maximum amount of letters to iterate through
for index in range(letters):
if simon_pattern[index] == user_pattern[index]:
user_score += 1 #adds 1 to user_score for each equal
#character in the same index for both strings
else:
break #if two characters do not match then end the loop
print('User score:', user_score)
using the break statement just gets you out of the nested loop (j). To solve this problem, you can either use a function with a return statement:
def get_user_score():
user_score = 0
simon_pattern = input() #input for initial string
user_pattern = input() #best attempt at copying simon_pattern
for i in user_pattern:
for j in simon_pattern:
if i == j:
user_score += 1 #adds 1 to user_score for each equal
#character in the same index for both strings
else:
return return user_score #if two characters do not match then end the function
return user_score
print('User score:', get_user_score())
or throw an exception:
try:
for i in user_pattern:
for j in simon_pattern:
if i == j:
user_score += 1 #adds 1 to user_score for each equal
#character in the same index for both strings
else:
raise RuntimeError() #if two characters do not match then end the loop
except RuntimeError:
pass
print('User score:', user_score)
I don't understand why I cannot go out from simple loop.
Here is the code:
a = 1
#tip checking loop
while a != 0:
# tip value question - not defined as integer to be able to get empty value
b = input("Give me the tip quantinty which you gave to Johnnemy 'hundred' Collins :")
# loop checking if value has been given
if b:
#if b is given - checking how much it is
if int(b) >= 100:
print("\nJohnny says : SUPER!")
elif int(b) < 100:
print("\nJohnny says : Next time I spit in your soup")
elif b == '0':
a = 0
else:
print("You need to tell how much you tipped")
print("\n\nZERO ? this is the end of this conversation")
Thanks for your help.
This should solve your problem:
a = 1
#tip checking loop
while a != 0:
# tip value question - not defined as integer to be able to get empty value
b = input("Give me the tip quantinty which you gave to Johnnemy 'hundred' Collins :")
# loop checking if value has been given
if b:
#if b is given - checking how much it is
if int(b) >= 100:
print("\nJohnny says : SUPER!")
elif int(b) < 100:
print("\nJohnny says : Next time I spit in your soup")
if b == '0':
a = 0
else:
print("You need to tell how much you tipped")
print("\n\nZERO ? this is the end of this conversation")
the following condition
if b == '0':
a = 0
should be in the same scope as the if b: condition.
You cant break out of the loop because. actually, there is nobreak. You need to putbreak` command at the end of every loop branch where you would like to stop looping in order to break out of the loop.
Also, you could break out assigning a = 0 instead of the break.
Specifically: We are to print out how many of the guess character are exactly right (correct character in the
correct position) and
and how many of the guess characters are correct values but are not in the correct
position.
Here's my code:
key = input("Input your secret key (RYBGWO):")
print("You are playing Mastermind whose purpose is to guess the secret key.")
print("Six colors are to be inputed with no repeats (RYBGW0).")
Answer = input("Please enter your 4-letter guess (RYBGWO):")
Answer_count = 0
my_string = "RYBGWO"
history = ''
while Answer.upper() != key:
ANSWER = Answer.upper()
if Answer.count("R") > 1:
Answer = input("You can not have repeating characters, try again:")
continue
elif Answer.count("Y") > 1:
Answer =input("You can not have any repeating characters, try again:")
continue
elif Answer.count("B") > 1:
Answer = input("You can not have any repeating characters, try again:")
continue
elif Answer.count("G") > 1:
Answer = input("You can not have any repeating characters, try again:")
continue
elif Answer.count("W") > 1:
Answer = input("You can not have any repeating characters, try again:")
continue
elif Answer.count("O") > 1:
Answer = input("You can not have any repeating characters, try again:")
continue
elif not(Answer.isalpha()):
Answer = input("Error, guess must be letters only, try again: ")
continue
elif len(Answer) !=4:
Answer=input("Your guess must contain 4 letters (rybgwo).Try again:")
continue
if 'R' and 'Y' and 'B' and 'G' and 'W' and 'O' not in Answer:
Answer = input("ERROR: Only letters RYBGWO allowed. Try again:")
continue
for i, ch in enumerate(Answer):
correct_count = 0
correct_position = 0
wrong_position = 0
i = 0
if key[i] == Answer[i] and key[ch] == Answer[ch]:
correct_count += 1
correct_position +=1
i = [len(Answer)-1]
print("Correct color and position count:", correct_count)
elif key[ch] == Answer[ch] and key[i] != Answer[i]:
correct_count += 1
wrong_position += 1
i = [len(Answer)-1]
print("Correct color, wrong position:", )
else:
print("Congratulations! You won!")
Answer_count = Answer_count + 1
print("(",Answer_count,"of 8 guesses)")
history += "\n" + Answer
print("History:", history)
The line
if key[i] == Answer[i] and key[ch] == Answer[ch]:
does not make all that much sense. Using enumerate, i is the position, that's fine, but ch is the character at that position. key[ch] does not make sense. Did you mean key.count(ch)? But even then there is no easy way to get the "correct value at incorrect position" part easily with enumerate. Consider the case of "abcd" and "baca": Here, a has different count in both strings, and yet that should be +1 for correct_count
Instead, let me suggest this: For "correct value at correct position", just zip the two strings and compare the characters. The "correct value at incorrect position" case is a bit more difficult, but can be done by creating two Counter objects and &-ing those together.
>>> x = "abcd"
>>> y = "baca"
>>> Counter(x) & Counter(y)
Counter({'a': 1, 'c': 1, 'b': 1})
>>> [a == b for a, b in zip(x, y)]
[False, False, True, False]
When calculating the totals, remember that the correct_count number includes the correct_position number, so you need to subtract those:
>>> correct_position = sum(a == b for a, b in zip(x, y))
>>> correct_count = sum((Counter(x) & Counter(y)).values()) - correct_position
Down votes are coming because your criteria is not well defined, but I think that you are asking for a basic master-mind type problem. It is easy enough if you define your problem such that the hidden values do not repeat. If your hidden value, as I define it below can have repeating values than the problem gets more complex. It can be made to work - it just takes a bit more thought.
Anyway, here is a basic implementation that I've tested on my box.
hidden = ["red", "blu", "grn", "ylw", "gold", "ora"]
def check_answer(answer):
guess_num = 0
correct_position = 0
correct_location = 0
for guess in answer:
text = "value not found"
if (len(hidden) <= guess_num):
break
if guess == hidden[guess_num]:
correct_position += 1
text = "correct value and position"
elif guess in hidden:
correct_location += 1
text = "correct value, wrong position"
guess_num += 1
print("guess {} = {} ; {}".format(guess_num, guess, text))
ans1=["red", "grn", "blu", "ylw"]
ans2=["red"]
check_answer(ans1)