Python Program, while loop not executing? - python

Names=[0,1,2,3,4]
Names[1]=='Ben'
Names[2]=='Thor'
Names[3]=='Zoe'
Names[4]=='Katie'
Max=4
Current=1
Found=False
PlayerName=input('What player are you looking for?')
while Found==False and Current==Max:
if Names[Current]==PlayerName:
Found=True
else:
Current+=1
if Found==True:
print('Yes, they have a top score')
else:
print('No, they do not have a top score')
This is the program. When any of the 4 names at the top are entered, the program should print, 'Yes, they have a top score', but when anything else is entered it should print,'No, they do not have a top score'.
However whatever name is entered it returns the 'No, they do not have a top score' message. I think it may have something to do with the loop but not sure what.

Your second condition is inverted. You want
while Found==False and Current!=Max:
That said, in Python you can do this much more simply using the in operator:
names = ['Ben', 'Thor', 'Zoe', 'Katie']
player_name = input('What player are you looking for?')
if player_name in names:
print('Yes, they have a top score')
else:
print('No, they do not have a top score')
That way, you don't need the while loop at all.

Names[1]=='Ben'
...
Is not assignment, it is equality check (and it returns False, although this is irrelevant)
Hence, your list is not modified, and names are checked against the list [0,1,2,3,4], and they never match, which is not a surprise.
Additionally, your loop condition is incorrect, and the code there is never run.
You should however consider writing your program is a more pythonic way, using the in operator, as suggested above, or a least using a for loop, iterating over your list.

In your while loop, you're doing these comparisons:
Found==False and Current==Max
The second part of the condition will never evaluate to True because Current is always set to 1 before the loop, which is != to Max - therefore, the code in the loop never evaluates.

Look here:
Names=[0,1,2,3,4]
Names[1]=='Ben'
Names[2]=='Thor'
Names[3]=='Zoe'
Names[4]=='Katie'
This doesn't do what you think it does. Afterwards, Names is equal to [0, 1, 2, 3, 4]. The next few lines don't assign names to Names but only check whether an element is equal to a name. For example, Names[1]=='Ben' checks if the second element in Names is equal to Ben (so this evaluates to True or False) but nothing is done with the result.

Your code never enters inside while loop, because initially Current = 1 and Max = 4, so they are not equal.

Do you try to program BASIC in Python? :-)
Others have answered why it does not work. Even if you do these changes, your program does look more like BASIC than like Python.
You should do the following:
Use index 0 as well. You allocate 0..4 and use 1..4. Just use 0..3.
iterate through a list with for item in listobject: instead of the while loop.
Don't do if Found==True:, just use if Found:
Don't name your variables with starting uppercase - these names are for classes. Use found instead of Found.

Related

Using while-loop and input(), how can the answer be stored in different variables without using list?

For instance,
while True:
variable_a = input()
So, this while loop will keep asking for input.
If I want the first input from users be stored in "variable_a", and the second input be stored in a different variable, let say "variable_b". What should I do without using two input() statements?
Actually I want to compare these two inputs. Like this
if variable_a == variable_b:
print("Yes")
But I don't know how to do that with only one input() statement.
If you are comparing an incoming value to a previous one in an infinite loop, you can have an implementation that is aware of those states (like "current" and "previous"). For example:
previous = None
while True:
current = input()
if current == previous:
# continue counting
else:
# do something else
previous = current # shift value to 'previous' for the next cycle
It is only possible if you use:-
. Array
.Sets or tuples
or
.String:Store the variables in a string string=string+space+character inside a loop. And then seperate them through spaces between them.*
The string one is the way you could do.

Trouble understanding break vs else statements with nested loops

I'm practicing python and one of the coding tasks assigned was to create a function that looks through a list and ignores numbers that occur between a 6 and a 9 and returns the sum of all other values.
Edit: this does not mean to add numbers whose values are less than 6 or greater than 9. It means to add all numbers of any value, but to ignore any numbers that come after a 6, until a 9 is seen. Symbolically if i means include and x means exclude, the code should return all the values marked as i:
[i,i...6, x,x,...,9,i,i...,6,x,x,...]
In other words, 6 turns off adding and if adding is off, 9 turns it back on.
Note that a 9 with no preceding 6 is just a number and will be added.
For example if I have a list:
[4,5,6,7,8,9,9]
the output should be:
8 <---(4+5+9)
The solution is provided but I'm having trouble understanding the code. I don't understand the purpose of the break statements in the code. The solution provided is as follows:
def summer_69(*arr):
total = 0
add = True
for num in arr:
while add == True:
if num!=6:
total = total + num
break
else:
add = False
while add == False:
if num !=9:
break
else:
add = True
break
return total
I'm really confused how the break statements help with the code. Particularly, I'm confused why the first 'break' is needed when there is already an 'else'.
The second break confuses me as well.
I understand that 'break' statements stop a loop and go onto the next loop.
My interpretation of the code so is 'if the number does not equal to 6 then total = total + num, if it does equal 6 then the loop is broken and if it is broken, add changes to False'.
I'm not sure if that interpretation is correct or not.
I was wondering how seasoned Python coders interpret 'breaks' vs 'else'.
break will exit whatever loop the statement is in. It's useful for many things, but often it's used to "short-circuit" the loop. If we know that the rest of the loop is irrelevant after some condition is met, then it's just wasted resources to keep looping through.
The break statement allow you to leave the while loop, but the if else statement allow you to stay in loop, until the condition of the while loop change or a break statement is in the action into the while loop
The solution you've provided is extremely convoluted and hard to understand.
A much better solution is:
total = 0
for num in arr_2:
if(num >= 6 and num <=9):
continue
total += num
Or a more pythonic way:
filtered_arr = filter(lambda x: x <6 or x > 9, arr_2)
total = reduce(lambda x, y: x + y, arr)
Anyways, in your solution, the first break is absolutely redundant. The reason why there is a break there, is because when you've found a number that doesn't equal 6, you add it, and you get out of the while loop.
In other words, the solution should have used an if statement, instead of the while statement. The break is there to basically have the while loop execute once.
Because, if a number does equal 6, then add will be false, and the while loop will terminate. If a number does not equal 6, you get out of the while loop. So the while loop is pointless, and meant to be an if statement instead.
This is a tricky way to handle program flow with a toggle nested in conditional loops.
It's a little hard to follow, but it is a well-known classic pattern.
Initially ADD == True, so if we start with a number that is not 6 (as in your example), the algorithm adds the number & breaks out of the first while loop. When it breaks, the next statement executed will be the line while add == False
At this point ADD == TRUE so the second while loop will not be entered. The next statement executed will be for num in arr (the outermost loop).
The outer FOR loop will go again and this process will repeat.
When you encounter a 6, the number will not be added and the break will not occur. The program will execute the else clause, setting ADD = FALSE.
After the else clause, execution continues with statement while add == false. Since ADD == FALSE at this point, the second while loop will be entered.
From now on ADD will be FALSE so the first While loop will not be entered and numbers will not be added. Instead, the condition for the second while loop will be evaluated for each number. As long as numbers are not equal to 9, the second while loop will not be entered.
When you encounter a 9, you will enter the second while loop, switch ADD back to TRUE, and break out of the while loop.
The first 9 comes after a 6 (ADD is FALSE) so it just toggles ADD from FALSE to TRUE and the number 9 doesn't get added.
When the NEXT 9 is encountered, ADD is TRUE and the number is not 6, so the first while loop will be entered and the number 9 will get added.
This is a classic pattern that used to be used in assembly language code perhaps 40 years ago. As written, the IF statements toggle a state variable. The state variable is turned on when the start condition is met, and turned off when a stop condition is met. The while loops ensure that the toggle can only be turned ON when it was OFF and vice versa, and provide places to put in different handling when the state is ON vs when it is OFF. This pattern brings certain efficiencies that are completely irrelevant in modern high-level languages.
There are better ways to do this in all modern languages, but as an exercise in following tricky program flow it's quite good :)

Looping for loop in Python

I have the following code.
for idx in range(len(networks)):
net_ = networks[idx]
lastId=0
for layerUptID in range(len(net_[1])):
retNet,lastId=cn_.UpdateTwoConvLayers(deepcopy(net_),lastId)
networks.append(retNet)
if(lastId==-1):
break
networks has only one net at the beginning.
After running the line retNet,lastId=cn_.UpdateTwoConvLayers(deepcopy(net_),lastId), I have additional six nets and appended to networks.
So after this lastId ==-1, go back to first for loop with len(networks) is 7.
For the next idx, idx=1 and continue.
Then, len(networks) is 13. Then go back to first for loop.
After this, the first for loop breaks.
I am expecting to continue for idx is 2, but it breaks.
What could be the issue?
If you try using a WHILE loop instead of FOR loop, the break statement would be check if the loop is on the last item in 'networks' collection.
This way the network length would be calculated in each loop iteration
For starters: Iterating, or looping, over the list (or data) you're editing is bad practice. Keep that in mind while coding.
This means if you plan to edit what you're looping on, in your case networks, then you're going to have a bad time looping over it. I would advise to break it up into two code parts:
The first part creates a new list of whatever it is you want WHILE looping.
The second part replaces the list you've used to generate what you wanted.
Another thing which could go wrong is net_[i] may not be set up for some i, and you're trying to access it here:
for layerUptID in range(len(net_[1])):
What if there is nothing in net_[1]?
To avoid these errors, usually verifying your data is a great way to start. If it is not null, then proceed, otherwise, print an error.
This is what I can think of. Hope it helps.
If I understood correctly your problem is that you've added new elements to networks, i.e. have increased length of networks and expect that for-loop will pick up this changes, well it's not, let's look at following snippet
elements = [1]
indices = range(len(elements))
for index in indices:
print('index is', index)
elements.append(2)
print('elements count is', len(elements))
print('indices count is', len(indices))
outputs are
index is 0
elements count is 2
indices count is 1
so as we can see despite the fact that length of elements list has changed, range object which is used in for-loop has not. This happens because len returns int object which are immutable, so when you change list length its length becomes different object and range function has no idea about this changes.
Finally, we can use while loop here like
while networks:
net_ = networks.pop()
lastId = 0
for layerUptID in range(len(net_[1])):
retNet, lastId = cn_.UpdateTwoConvLayers(deepcopy(net_), lastId)
networks.append(retNet)
if lastId == -1:
break

How could this function be implemented without recursion?

I'm trying to do a bingo game, I had some struggle with it but finally sorted it out.
However, my main "problem" (more like, I've heard its bad programming) is that with my function I'm calling my function inside it in an else statement. I don't think that it's how you suppose to do it, i have not found any way around it though.. Because this function is called from another function called menu() so when i use a loop, it goes back to the menu if false.
Here's my code:
def selectingNumbers():
numbers = []
dupl = []
j = 0
print("Now you are gonna select 5 number\n")
while j < 5:
nummer = int(input("Your choice:\n"))
numbers.append(int(nummer))
j = j+1
for i in numbers:
if i not in dupl:
dupl.append(i) #New list without duplicates
if dupl == numbers: #Comparing new list with old list
print("No equal numbers found")
dragning(numbers)
else:
print("Equal numbers found")
selectingNumbers() #Is there a better way to do it?
I also had some issues with the list at the beginning, I know I can use the set() function but i want to keep the original list as it is and compare the new one with the old one, can I do that in a better way with "real" programming instead of import modules?
Hope you can answer or guide me on these two questions with alternatives and if so, say why my code is "bad" if it is.
Well you have to decide if you want to use recursion to solve the problem. This line is a recursive call:
selectingNumbers() #Is there a better way to do it?
Which is fine, and does not equate to bad programming. However, the rest of your function does no cater to a recursive function. You reset your variables and have no true base case because of that. See google, or here for examples.
Recursion is confusing for beginners, so I would take an iterative only approach. Here is a bingo python example.
In addition, I'm not sure this line works:
if dupl == numbers: #Comparing new list with old list
I am not too familiar with python, but in my experience, arrays are treated as objects, so in that line you would be asking python to compare two seperate objects with unique references in memory. So they will never be equal, even if the values inside of them are the same because they are both referenced seperately. I found this link to answer that concern.
Recursion isn't "bad". In fact it can sometimes greatly simplify a solution to a problem. However in the case of your code it isn't necessary. Fortunately, it can sometimes be replaced with a loop. In the case of your code it looks like it could just loop until it gets a list from the user that doesn't contain any duplicates. That means it could be rewritten as shown below (I also simplified a few other things):
def selectingNumbers():
while True:
print("Now you are gonna select 5 different numbers\n")
numbers = []
for _ in range(5):
number = int(input("Your choice:\n"))
numbers.append(number)
unique = set(numbers) # will remove any duplicates
if len(unique) == len(numbers): # no dups?
print("No equal numbers found")
break # <--- terminates loop
else:
print("Equal numbers found")
# allow loop to continue
dragning(numbers)

Python IndexError : string index out of range in substring program

I am writing a code for a class that wants me to make a code to check the substring in a string using nested loops.
Basically my teacher wants to prove how the function 'in', as in:
ana in banana will return True.
The goal of the program is to make a function of 2 parameters,
substring(subStr,fullStr)
that will print out a sentence saying if subStr is a substring of fullStr, my program is as follows:
def substring(subStr,fullStr):
tracker=""
for i in (0,(len(fullStr)-1)):
for j in (0,(len(subStr)-1)):
if fullStr[i]==subStr[j]:
tracker=tracker+subStr[j]
i+=1
if i==(len(fullStr)-1):
break
if tracker==subStr:
print "Yes",subStr,"is a substring of",fullStr
When i called the function in the interpreter 'substring("ana","banana")', it printed out a traceback error on line 5 saying string index out of range:
if fullStr[i]==subStr[j]:
I'm banging my head trying to find the error. Any help would be appreciated
There are a few separate issues.
You are not reseting tracker in every iteration of the outer loop. This means that the leftovers from previous iterations contaminate later iterations.
You are not using range, and are instead looping over a tuple of just the 0 and the length of each string.
You are trying to increment the outer counter and skipping checks for the iteration of the outer loop.
You are not doing the bounds check correctly before trying to index into the outer string.
Here is a corrected version.
def substring(subStr,fullStr):
for i in range(0,(len(fullStr))):
tracker=""
for j in range(0,(len(subStr))):
if i + j >= len(fullStr):
break
if fullStr[i+j]==subStr[j]:
tracker=tracker+subStr[j]
if tracker==subStr:
print "Yes",subStr,"is a substring of",fullStr
return
substring("ana", "banana")
First off, your loops should be
for i in xrange(0,(len(fullStr))):
for example. i in (0, len(fullStr)-1) will have i take on the value of 0 the first time around, then take on len(fullStr)-1 the second time. I assume by your algorithm you want it to take on the intermediate values as well.
Now as for the error, consider i on the very last pass of the for loop. i is going to be equal to len(fullStr)-1. Now when we execute i+=1, i is now equal to len(fullStr). This does not fufill the condition of i==len(fullStr)-1, so we do not break, we loop, and we crash. It would be better if you either made it if i>=len(fullStr)-1 or checked for i==len(fullStr)-1 before your if fullStr[i]==subStr[j]: statement.
Lastly, though not related to the question specifically, you do not reset tracker each time you stop checking a certain match. You should place tracker = "" after the for i in xrange(0,(len(fullStr))): line. You also do not check if tracker is correct after looping through the list starting at i, nor do you break from the loop when you get a mismatch(instead continuing and possibly picking up more letters that match, but not consecutively.)
Here is a fully corrected version:
def substring(subStr,fullStr):
for i in xrange(0,(len(fullStr))):
tracker="" #this is going to contain the consecutive matches we find
for j in xrange(0,(len(subStr))):
if i==(len(fullStr)): #end of i; no match.
break
if fullStr[i]==subStr[j]: #okay, looks promising, check the next letter to see if it is a match,
tracker=tracker+subStr[j]
i+=1
else: #found a mismatch, leave inner loop and check what we have so far.
break
if tracker==subStr:
print "Yes",subStr,"is a substring of",fullStr
return #we already know it is a substring, so we don't need to check the rest

Categories

Resources