Why is my loop not following its condition? - python

so im working on this code for school and i dont know much about python. Can someone tell me why my loop keeps outputting invalid score when the input is part of the valid scores. So if i enter 1, it will say invalid score but it should be valid because i set the variable valid_scores= [0,1,2,3,4,5,6,7,8,9,10].
This code has to allow the user to enter 5 inputs for six different groups and then add to a list which will find the sum of the list and the avarage of the list.
Code:
valid_scores =[0,1,2,3,4,5,6,7,8,9,10]
for group in groups:
scores_for_group = []
valid_scores_loops=0
print("What do you score for group {group_name} as a player?"\
.format(group_name=group))
while valid_scores_loops < 5:
valid_scores=True
player_input =input("* ")
if player_input==valid_scores:
player1.append(player_input)
scores_for_player.append(int(player_input))
else:
if player_input!=valid_scores:
valid_scores= False
print("Invalid score!")

You're setting valid_scores=True, which overwrites your list of valid scores with a boolean value of True. Then, when you check player_input!=valid_scores, it will always return False.
What you want to do is get rid of the valid_scores=True line, cast the player_input to an integer using int(player_input), then check int(player_input) in valid_scores. This will return True if the player inputs a string that can be cast to one of the integers in valid_scores.

In your code there you are comparing a list (the valid values) with a string (the input.) This means you would have to give in a list for the statement to be correct. The right way is input in valid_inputs, which will check if any of the elements in the valid_inputs list equals the variable input. You're also assigning True to valid_inputs, which essentially deletes the list. Another error is that the player1 and scores_for_player variables aren't defined in your code. To fix your code, you'll have to cast the input to an integer, the variable storing if the input is valid must be renamed, the variables player1 and scores_for_player must be declared, and you probably should adjust your code with the fixes below.
You can also improve your code by replacing while valid_score_loops < 5 with for valid_score_loops in range(5) because you don't change valid_score_loops in loop. Another way for you to express [0,1,2,3,4,5,6,7,8,9,10] is to convert it to a tuple: (0,1,2,3,4,5,6,7,8,9,10) or express it as a range: range(0, 11).
Ranges are objects like lists and tuples that contain a sequence of numbers. The signatures of the range method are:
range(end) with start equivalent to 0 and step to 1
range(start, end) with step equivalent to 1
range(start, end, step)
It will start at start and increase by step each time, ending before end.
Example:
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(range(3, 5))
[3, 4]
>>> list(range(1, 6, 2))
[1, 3, 5]
There is another optimization to make to your code. If the input isn't valid, it is invalid, so you don't have to check that in your code. To fix that, you can just remove the check if the argument isn't in the valid_scores list inside the else clause.

Related

Why it is not possible to for-loop a list of numbers and increment each number directly?

Why will the following code increment each number:
numbers = [1, 2, 3]
for number in numbers:
numbers[numbers.index(number)] += 100
print(numbers) # prints [101, 201, 301]
but this will not?:
numbers = [1, 2, 3]
for number in numbers:
number += 100
print(numbers) # prints [1, 2, 3]
Adding to the confusion, we seem to be dealing with same object in both cases:
numbers = [1, 2, 3]
for number in numbers:
print(numbers[numbers.index(number)] is number) # prints True
I understand this has "something" to do with assigning vs mutating a value and/or memory allocation, but I cannot put my finger on what exactly is happening.
numbers[x] is just a different syntax for numbers.__getitem__(x) (when used as an rvalue) or numbers.__setitem__(x, y) (when used as an lvalue).
So in your first example, the __setitem__() method of the numbers lists is called to update the list. Under the hood your code is roughly translated to something like this:
for number in numbers:
index = numbers.index(number)
new_value = numbers.__getitem__(index) + 100
numbers.__setitem__(index, new_value)
Note that above code is valid Python and has the same effect as your original loop.
In your second example, the values are retrieved from the list and stored in a local variable number, which you then overwrite. This has no effect on the original list.
NB: Also note that comparing integers using is may lead to unexpected behaviour. See for example this SO post for more details about that.
Think of it as thus:
for number in numbers:
is roughly the same as:
for i in range(len(numbers)):
number = numbers[i]
Now, in the second case it becomes more obvious that adding
# number += 100 # which is not a mutation, but a rebinding equivalent to
number = number + 100
simply reassigns the variable number and that numbers[i] is and should be unaffected. This holds for the first loop variant, too.

Trying to add the first & last integer of a list in python

Hi I have just started an online course for python, just for me, and one of the exercises is asking me to add the first and list integer from a list you input, I think I have it, but not too sure as it keeps giving me an error,
ValueError: invalid literal for int() with base 10
my code is
userList = list(map(int, input().split(',')))
intTotal = userList[1] + userList[len userList]
print (intTotal)
now, how I understand it the, [1] would be the first userList value, as it is the first position in the list, and the [len userList] should give me last position as it is giving the length of list as position number.
then it should print the variable intTotal
If you could show me where i am going wrong if it all that would be ace!
Your error is most likely that your input is something like 1, 2, 3, 4, 5,
When you use split(',') on this, you will have an extra empty entry at the end of your list that you must account for. You can check for this in a list comprehension.
To access the last element of the list, you may use arr[len(arr)-1], or in Python which supports negative indexing, arr[-1].
Here is a working version of your code with the above changes made:
userList = [int(x.strip()) for x in input().split(',') if x]
intTotal = userList[0] + userList[-1]
print (intTotal)
Sample run:
>>>1, 2, 3, 4, 5,
6
You could make this even more robust to filter out bad input by using isdigit(), which would allow for the user to enter letters, but it would only add the first and last numbers entered:
userList = [int(x) for x in input().split(',') if x.isdigit()]
Sample run:
>>> 1,2,a,3,4,6,b,4
5

Factorial list in python 3 not running

I'm still a beginner so please bear with me. So I'm trying to get a list of factorial numbers from 1 to 5.
factorial=[]
for i in range(1,5):
for x in range(1,5):
while(i>x):
factorial.append(i*x)
When I switch out the factorial.append for print it just continously spits out 2s, does anyone know why, and if so what to do to fix this and what other viable method is there to get a list of factorial numbers?
I this case, I recommend you to use a recursive function:
def factorial(x):
if x == 1:
return 1
else:
return x*factorial(x-1)
Ex:
>>>factorial(5)
120
>>>factorial(10)
3628800
you can do something like :
>>> f=[1] # initialized your list
>>> for i in range(5): # take each value in the list [0,1,2,3,4]
... f.append(f[i]*(i+1)) #to create a next point multiply with the last value
...
>>> f=f[1:] #don't keep the first (repeated) point
>>> f #you have your list !
[1, 2, 6, 24, 120]
You're getting stuck in your while loop.
If you go step by step through your code, you'll see what is going on:
In the first loop, i value will be 1, and x values from 1 to 5, so i will never be > than x, thus you won't enter the while loop.
At the start of the second loop, i value will be 2 and x value will be 1, so you will enter the while loop.
You will stay in stay in the while loop until i becomes lower or equal to x, but this will never happen because to continue with the for loop you'll need to exit the while loop first.
Despite the error, i do not understand the reasoning that brought you there.
The common way to handle factorials is with recursion, as #Julio CamPlaz's answer shows, but it may simplier to understand the following:
# in each for loop, you multiply your n variable for the i value
# and you store the result of the moltiplication in your n variable
n=1
for i in range(1,6): # if you want the numbers from 1 to 5, you have to increase by one your maximum value
n = n*i
print n

How to find elements in one arbitrary list that occur in another list (preserving their order)?

I need to create an algorithm which would read user input of lists A and B and determine whether elements from list B occur in list A (if they occur, program needs to print 'Yes', and 'No' otherwise').
I have come up with the following code which should can be a starting point:
n=int(input('Enter the length of list A '))
A=[]
for i in range (0,n):
InpEl=int(input('Enter the elements '))
A.append(InpEl)
print(A)
n=int(input('Enter the length of list B '))
B=[]
for i in range (0,n):
InpEl2=int(input('Enter the elements '))
B.append(InpEl2)
print(B)
checklist=B
for each in A:
if each in checklist:
print('YES')
else:
print('NO')
Although in any case, I get 'No'. What is the mistake here?
Also, later I may need to modify the list so the program could determine if elements of B occur in A in the order they appear in B, but not necessarily consecutively.
For example, let M be the length of B and N be the length of A.
Then the program should return yes if there are indices i0, i1...im+1 such that 0<= i0 < i1...< im-1 < N such that A[i0] = B[0];A[i1] = B[1]...A[im-1] =
B[m-1].
Is there a simpler way to build the loop which would satisfy this kind of request?
P.S.: is it possible to make user input read not only integers, but strings? I am not sure if raw_input would be useful in Python 3.5.
P.S.S:
sorry, I made a minor mistake inputting the code here, I fixed it now.
Another question: I get the output of multiple yes' and no's for each element:
Enter the length of list A 3
Enter the elements 1
Enter the elements 2
Enter the elements 3
[1, 2, 3]
Enter the length of list B 3
Enter the elements 5
Enter the elements 4
Enter the elements 3
[5, 4, 3]
NO
NO
YES
How can I modify the code so it would print only one yes and no only once in case of any occurencies happen?
Here's one solution. Keep in mind there are many that have asked this type of question before and that best practice is to search around before asking.
a = input('enter list A with comma between each element: ')
b = input('enter list B with comma between each element: ')
a = a.split(',')
b = b.split(',')
contained_in_b = [element in b for element in a]
for i, in_b in enumerate(contained_in_b):
print('element {} contained in list B: {}'.format(a[i], in_b))
Better to take the raw input all together and use Python to split it into lists. This way, no need for the user to give the length of the list beforehand. Also, no need to convert to int - string comparisons work fine.
contained_in_b uses a list comprehension - a handy feature of Python that applies the boolean element in b to each element in a. Now you have a list of True/False values that you can enumerate through to print out the desired output.
One weapon you get is the all operator, which just checks that all of the items in the iterable are True:
A = [1, 4, 6, 8, 13]
B = [4, 6, 13, 8]
C = [3, 8, 25]
master = [i for i in range(20)]
print all(i in master for i in A)
print all(i in master for i in B)
print all(i in master for i in C)
Output:
True
True
False
To get the order as well, you'll need to drop back to an iterative method, stepping through the first list with a loop, while you maintain an index to know where you are in the second. For each value in the first list, go through the rest of the second list, until you either find the item (temporary success) or hit the end (failure).
Reading in number names and converting them to integers is a separate problem, and longer code.

How to check consecutive number in list?

This is my homework.
The problem is to find a way to check whether the items in a list are consecutive or not.
The following is code I've written:
def consecutive(var):
for x in range(2, len(var)):
forward = var[x] - var[x-1]
backward = var[x-1] - var[x-2]
if forward == backward:
return True
else:
return False
var = []
print 'Enter your number:'
while True:
num = raw_input()
if num == '':
break
var += [int(num)]
print consecutive(var)
If I input numbers like 1, 2, 3, 4, 5 then I will get True
If I input numbers like 2, 6, 3, 9, 7, 1, 4 then I'll get False
Here, I succeeded returning True or False values respectively.
But there're two questions that make me upset because if I use my code to solve the questions, I don't get the value that I want (it gives me an error)
First question: Is an empty list considered a consecutive list or not?
Second: Is a list that involves a single value considered a consecutive list or not?
Would you like to help me?
By mathematical convention as discussed in the comments, it would be standard to consider both an empty list and a list with a single element as consecutive, should it not be specified in your homework more precisely.
By the logic of vacuous truth, were a list to not have consecutive order it would require enough elements (2) to break this condition of ordering. To handle this in your existing code, you could simply perform a check before your main check to ensure the base cases of an empty list and a list with one element return True.

Categories