I'm coding a small game for fun where the computer randomly chooses 4 colors as a secret code and the user's job is to guess what they think the colors are, with clues being given based on how close you are to the secret code. When an element in your guess list is a match, the program appends a clue value of 2 to a new list and if the element in your guess list doesn't match the position but occurs in the secret code list, it should append a value of 1 to our clue list.
A problem I'm having is when you compare your list of guesses with the secret code list. Here is an example:
say if the computer secret code is a list with 4 elements as shown: ["Blue", "Yellow", "Green", "Red"]
and your guess is ["Blue", "Blue", "Green", "Red"], the program returns a clue list[2, 1, 2, 2]. I want it to return [2, 2, 2] because I don't want to double count the Blue guess in the guess list when it only occurs once in the secret code.
Here is the code for the function so far.
def get_clue(secret_code, guess_list):
clue_list = []
for i in range(len(guess_list)):
if guess_list[i] == secret_code[i]:
clue_list.append(2)
elif guess_list[i] != secret_code[i] and guess_list[i] in secret_code:
clue_list.append(1)
else:
clue_list = clue_list
print("Your Clue is : ", clue_list)
return clue_list
The first change I would make is to take out some redundant code:
The condition of the elif can be shortened - we already know that guess_list[i] != secret_code[i] if the first if-statement didn't get executed, so we don't need to check for that explicitly.
Additionally, your else branch does nothing, so why even include
it? You can safely remove that as well.
I would remove the print statement as well. I wouldn't expect a
function with a prefix of get_ to have a printing side-effect. If
you need to print the contents of the clue_list, do that in the
calling-code once get_clue returns.
With these changes, your code looks like this:
def get_clue(secret_code, guess_list):
clue_list = []
for i in range(len(guess_list)):
if guess_list[i] == secret_code[i]:
clue_list.append(2)
elif guess_list[i] in secret_code:
clue_list.append(1)
return clue_list
Here's the second round of changes I would make:
The name get_clue isn't entirely accurate to describe this
function. This function returns a list of clues, so I think a better
name would be get_clues.
secret_code isn't a great name for the first parameter. It's a list
of secrets. I would either call it secrets or secret_codes.
guess_list isn't a great name for the second parameter. We can see
that this object is a list by virtue of the fact that we are doing
list-like things with it, so don't include "list" in the name. I
would ditch this nasty habit of including the type of the variable in
the variable's identifier. A better name would be guesses.
Same thing goes for clue_list. We already know it's a list. Don't
make "list" part of the name. A better name would be clues.
Instead of working with indices (plural of "index"), we can get more
Pythonic by using zip to iterate through both lists at the same
time.
With these changes your code now looks like this:
def get_clues(secrets, guesses):
clues = []
for secret, guess in zip(secrets, guesses):
if guess == secret:
clues.append(2)
elif guess in secrets:
clues.append(1)
return clues
With that out of the way, you said:
I want it to return [2, 2, 2] because I don't want to double count the
Blue guess
Wouldn't you want the clues to always have four elements, though? If my guess is ["Blue", "Blue", "Blue", "Blue"], and get_clues returns [2], I have no way of knowing where Blue actually is.
You could use a set to keep track of previously made guesses:
def get_clues(secrets, guesses):
clues = []
previous_guesses = set()
for secret, guess in zip(secrets, guesses):
if guess == secret:
clues.append(2)
elif guess not in previous_guesses and guess in secrets:
clues.append(1)
previous_guesses.add(guess)
return clues
Related
Here's what I have been asked to do:
Create a program that will use 2 Lists to store details about guests invited to a wedding.
Method:
Set up two lists - one for the names of the guests and one to store whether the invitation has been accepted or not. NOTE the second array should be a list of boolean elements that are initially set to false
You need to ask for the names of the guests and then ask if they are attending the wedding.
Print out a list of only those who will attend.
Here is what I have done:
names = [""]*10
accept = [False]*10
accepted = [""]*10
counter = 10
for counter in range(0,10):
names[counter] = str(input("What is your name?"))
accepted[counter] = input("Are you accepting the invitation?")
if accepted[counter] == "Yes" or accepted[counter] == "yes":
accept[counter] = True
else:
names[counter] = ""
print("Here is a list of peoples names whom are attending:")
print(names)
And here is what my teacher said:
Works but can you think of a better way to display the names of those attending?
Are you able to help me work this out, I think the teacher wants me to remove the name from the list however I don't know how to do this. I have tried using pop() but I just don't understand it. :(
The names list is supposed to contain all the people who were invited, you shouldn't replace a name with an empty string, because then it won't be complete.
Use a loop to print the names of just the people who are attending, using the index in the corresponding element in the accepted list.
There's also no need for accepted to be a list. Just use an ordinary variable for the current answer.
names = [""]*10
accept = [False]*10
for counter in range(0,10):
names[counter] = input("What is your name?")
accepted = input("Are you accepting the invitation?")
if accepted.lower() == "yes":
accept[counter] = True
print("Here is a list of peoples names whom are attending:")
for i, attending in enumerate(accept):
if attending:
print(names[i])
pop() is used to remove a value from a list. If used without parameters, it will remove the last value. If given a value it will "pop it", or delete it in other words, and print the deleted value.
I am trying to break out of a bad habit of using if/else too frequently. I am new to how functions work and the proper way to call them but I am constantly researching the correct way to implement them with my code. The code that I am making is suppose to check for 3 different words and if the word is not in the input then the user will receive a statement that says "rejected" if the word is correct it will say "accepted". The issue that I am facing is getting my program to work correctly. So far I have set up my program to check each index of the word and if it matches the full word it will be marked as accepted. I am trying to figure out the correct way to add a rejected flag and to avoid the error that I recieve after running this program.
def checker():
q0 = input("enter word:")
if (q0[0]) +(q0[1]) == "if":
print ("accepted")
if (q0[0]) + (q0[1]) + (q0[2]) + q0[3] == "else":
print("accepted")
if(q0[0]) + (q0[1]) == "do":
print("accepted")
else:
print("rejected")
checker()
For this program, I am not going to use a dictionary so I can correctly challenge myself and implement this in an automata fashion. How can I implement this code without getting the string index out of range error. I tried to put break after my print statement but it doesn't work.
Thanks in advance to everyone. This is my first post so if I have made any mistakes in my post please let me know!
Here's an extensible one-liner for you:
def check():
q = input().strip()
acceptable = {'if', 'else', 'do'}
print('accepted' if q in acceptable else 'rejected')
The variable acceptable is set; a data structure which is very quick to check if something is inside of it. You can modify this set (or pass it to check as an argument!) to change the range of acceptable words without changing the control flow of the program (as you would in your original if/else implementation that you're laudably trying to move away from).
EDIT: I guess it's not strictly a 'one-liner'...
First, why do you access each character of the input string, then concatenate them again, then compare to a target string("if", "else", "do")?
Second, why do you use if statements repeatedly if matching either one of them will lead to the same result (print("accepted")?
Try this:
def checker():
q0 = input("enter word:")
if q0 in ["if", "else", "do"]:
print("accepted")
else:
print("rejected")
checker()
Now, you just compare a string q0 to another (each element of the list ["if", "else", "do"]). Also, the first hit in the list will make stop comparing anymore and will continue on to print "accepted".
++ Just to let you know why are you seeing "index out of range error", you are accessing each character of q0 without knowing how many there are. So if the user inputs a string like a, there's no q0[1] or q0[2], but you're asking your program to access it. Thus index out of range error.
You can do this with a for loop and one if statement if that is better for you. Simply put all the accepted values into a list and check if each word is in q0.
def checker():
q0 = input('enter word:')
for i in ['if', 'else', 'do']:
result = ('accepted' if i in q0 else 'rejected')
if result == 'accepted':
break
print(result)
you can do it as one liner with lambda function.
checker = lambda q: print("accepted" if q in ["elif", "if", "else"] else "rejected")
checker()
here is a sample
>>> checker = lambda q: print("accepted" if q in ["elif", "if", "else"] else
"rejected")
>>> checker("if")
accepted
>>> checker("fool")
rejected
I'm making a very simple graphical program and am quite new.
nums = ["second", "third", "fourth"]
for colours in range(3):
numString = nums[colours]
inputWindow.getMouse()
colour1 = inputBox.getText()
inputBox.setText("")
instruction.setText("Please enter the {0} colour: ".format(numString))
Where I put 'colour1', I want it to cycle through colour1, colour2, colour3 and colour4 on each iteration (without using a long if statement). Dictionary cannot be used for this particular program.
At the end, the function returns all of these colours inputted from the user. I tried using a list but realised you can't use them for variable names.
Thanks for help.
Edit: Seeing as there's a lot of confusion (which I'm sorry for), I'll try and explain better:
My code up there is kind of strange and comes from nowhere. I'll simplify it:
def getInputs():
for colours in range(3):
colour1 = userInput()
return colour1, colour2, colour3, colour4
This is basically the gist. I wanna know if there's a way to cycle through the different variables where 'colour1 = userinput()' is (without using dictionary).
Editing to reflect the new information. The principal thing to keep in mind here is that you can use sequence types (list, dict, etc.) to collect your results.
def get_inputs():
# a list to collect the inputs
rval = []
for colours in range(4):
# range(4) will walk through [0,1,2,3]
# this will add to the end of the list
rval.append(userInput())
# after the for loop ran four times, there will be four items in the list
return rval
In case you really want to want return a tuple, the last line can be return tuple(rval)
I made a simple script that converts any input text into a "code" and can also translate it back. It only works one word at a time.
I want to make the script adds each new code to a list that is printed every time. For example, the first time you translate something, "HELLO" becomes "lohleci". The second time, I want it not only to show "world" = "ldwropx", but also state below everything translated so far.
I'm new to Python and have looked through forums for people with similar problems. The way I tried doing it (a segment was removed and put into a separate script), I get an error saying "local variable 'list' referenced before assignment." This is the code producing the error:
list = "none"
def list():
word = raw_input("")
if list == "none":
list = word + " "
print list
list()
else:
new_list = list + word + " "
list = new_list
print list
list()
list()
Your code has several problems, all of which are fixable with a bit more knowledge.
Don't use the name list for your own variables or functions. It's the name of a built-in Python function, and if you use that name for your own functions you won't be able to call the built-in function. (At least, not without resorting to advanced tricks which you shouldn't be trying to learn yet.)
You're also re-using the same name (list) for two different things, a variable and a function. Don't do that; give them different, meaningful names which reflect what they are. E.g., wordlist for the variable that contains a list of words, and get_words() for your function.
Instead of using a variable named list where you accumulate a set of strings, but which isn't actually a Python list, why not use a real Python list? They're designed for exactly what you want to do.
You use Python lists like this:
wordlist = []
# To add words at the end of the list:
wordlist.append("hello")
# To print the list in format ["word", "word 2", "word 3"]:
print wordlist
# To put a single space between each item of the list, then print it:
print " ".join(wordlist)
# To put a comma-and-space between each item of the list, then print it:
print ", ".join(wordlist)
Don't worry too much about the join() function, and why the separator (the string that goes between the list items) comes before the join(), just yet. That gets into classes, instances, and methods, which you'll learn later. For now, focus on using lists properly.
Also, if you use lists properly, you'll have no need for that if list == "none" check you're doing, because you can append() to an empty list just as well as to a list with contents. So your code would become:
Example A
wordlist = []
def translate_this(word):
# Define this however you like
return word
def get_words():
word = raw_input("")
translated_word = translate_this(word)
wordlist.append(translated_word)
print " ".join(wordlist)
# Or: print ", ".join(wordlist)
get_words()
get_words()
Now there's one more change I'd suggest making. Instead of calling your function at the end every time, use a while loop. The condition of the while loop can be anything you like; in particular, if you make the condition to be the Python value True, then the loop will never exit and keep on looping forever, like so:
Example B
wordlist = []
def translate_this(word):
# Define this however you like
return word
def get_words():
while True:
word = raw_input("")
translated_word = translate_this(word)
wordlist.append(translated_word)
print " ".join(wordlist)
# Or: print ", ".join(wordlist)
get_words()
Finally, if you want to get out of a loop (any loop, not just an infinite loop) early, you can use the break statement:
Example C
wordlist = []
def translate_this(word):
# Define this however you like
return word
def get_words():
while True:
word = raw_input("")
if word == "quit":
break
translated_word = translate_this(word)
wordlist.append(translated_word)
print " ".join(wordlist)
# Or: print ", ".join(wordlist)
get_words()
That should solve most of your problems so far. If you have any questions about how any of this code works, let me know.
I need to test if the user input is the same as an element of a list, right now I'm doing this:
cars = ("red", "yellow", "blue")
guess = str(input())
if guess == cars[1] or guess == cars[2]:
print("success!")
But I'm working with bigger lists and my if statement is growing a lot with all those checks, is there a way to reference multiple indexes something like:
if guess == cars[1] or cars[2]
or
if guess == cars[1,2,3]
Reading the lists docs I saw that it's impossible to reference more than one index like, I tried above and of course that sends a syntax error.
The simplest way is:
if guess in cars:
...
but if your list was huge, that would be slow. You should then store your list of cars in a set:
cars_set = set(cars)
....
if guess in cars_set:
...
Checking whether something is present is a set is much quicker than checking whether it's in a list (but this only becomes an issue when you have many many items, and you're doing the check several times.)
(Edit: I'm assuming that the omission of cars[0] from the code in the question is an accident. If it isn't, then use cars[1:] instead of cars.)
Use guess in cars to test if guess is equal to an element in cars:
cars = ("red","yellow","blue")
guess = str(input())
if guess in cars:
print ("success!")
Use in:
if guess in cars:
print( 'success!' )
See also the possible operations on sequence type as documented in the official documentation.
#Sean Hobbs:
First you'd have to assign a value to the variable index.
index = 0
You might want to use while True to create the infinite loop, so your code would be like this:
while True:
champ = input("Guess a champion: ")
champ = str(champ)
found_champ = False
for i in listC:
if champ == i:
found_champ = True
if found_champ:
print("Correct")
else:
print("Incorrect")