Python output iterating through list based on user input - python

I have been struggling with this code for a couple hours and am not seeing much in previous questions that relates to it. I've gone down the rabbit hole trying to make it work so I think it's pretty inefficient at this point as well as isn't outputting in the manner I'd like.
I am trying to get user input in the form of multiple grade entries, evaluate them based on grading criteria and then output the students grade in letter form
Any advice on getting it to output correctly or on any better coding techniques would be greatly appreciated. Thanks ahead of time from a novice coder.
Here is my code:
"""10.1 - write a program that reads a list of scores and then
assigns letter grades based on the criteria:
A if score is >= best - 10
B if score is >= best - 20
C if score is >= best - 30
D if score is >= best - 40
F otherwise
"""
grades_input = input("Enter Students scores seperated by a space: ") #get user input of student's grades
grades_list = grades_input.split() #split user input into a list
grades_list_valid = [ int(x) for x in grades_list ] #convert items into integers
number_of_students = []
for i in range(len(grades_list_valid)):
number_of_students.append(i)
for grade in grades_list_valid: #create criteria to assign each letter grade
best_score = max(grades_list_valid) #get the highest grade
if grade >= best_score - 10:
print("Student {}".format(number_of_students[i]), "score is {}".format(grades_list_valid[i]), "and grade is A")
elif grade >= best_score - 20:
print("Student {}".format(number_of_students[i]), "score is {}".format(grades_list_valid[i]), "and grade is B")
elif grade >= best_score - 30:
print("Student {}".format(number_of_students[i]), "score is {}".format(grades_list_valid[i]), "and grade is C")
elif grade >= best_score - 40:
print("Student {}".format(number_of_students[i]), "score is {}".format(grades_list_valid[i]), "and grade is D")
else:
print("Student {}".format(number_of_students[i]), "score is {}".format(grades_list_valid[i]), "and grade is F")
and here is the output:
Enter Students scores seperated by a space: 40 55 70 58
Student 3 score is 58 and grade is C
Student 3 score is 58 and grade is B
Student 3 score is 58 and grade is A
Student 3 score is 58 and grade is B
The desired output is:
Student 0 score is 40 and grade is C
Student 1 score is 55 and grade is B
Student 2 score is 70 and grade is A
Student 3 score is 58 and grade is B

Its because your first loop to get i is completing before you make use of i, then i is already 3 when you loop through to print the results. Instead you should get the index in your second loop like this:
grades_input = input("Enter Students scores seperated by a space: ") #get user input of student's grades
grades_list = grades_input.split() #split user input into a list
grades_list_valid = [ int(x) for x in grades_list ] #convert items into integers
best_score = max(grades_list_valid)
for i, grade in enumerate(grades_list_valid):
letter_grade = "F"
if grade >= best_score - 10:
letter_grade = "A"
elif grade >= best_score - 20:
letter_grade = "B"
elif grade >= best_score - 30:
letter_grade = "C"
elif grade >= best_score - 40:
letter_grade = "D"
else:
letter_grade = "F"
print("Student {} score is {} and grade is {}".format(i, grade, letter_grade))
and then eliminate the first loop.
After looking again at the question i also noticed you were grabbing the "best score" from the same list every time, which would make each student have the same score. Im guessing you just want to grab the score for each student. I updated my answer to work for that - not sure if it was your desired behaviour.
Edit: looked at it again and realized what you were doing with best score, fixed my answer here's the results when i run it:
Enter Students scores seperated by a space: "70 80 93 77 31"
Student 0 score is 70 and grade is C
Student 1 score is 80 and grade is B
Student 2 score is 93 and grade is A
Student 3 score is 77 and grade is B
Student 4 score is 31 and grade is F

grades_input = input("Enter Students scores seperated by a space: ") #get user input of student's grades
grades_list = grades_input.split() #split user input into a list
grades_list_valid = [ int(x) for x in grades_list ] #convert items into integers
number_of_students = []
for i in range(len(grades_list_valid)):
number_of_students.append(i)
i=0
for grade in grades_list_valid: #create criteria to assign each letter grade
best_score = max(grades_list_valid) #get the highest grade
print(i)
if grade >= best_score - 10:
print("Student {}".format(number_of_students[i]), "score is {}".format(grades_list_valid[i]), "and grade is A")
elif grade >= best_score - 20:
print("Student {}".format(number_of_students[i]), "score is {}".format(grades_list_valid[i]), "and grade is B")
elif grade >= best_score - 30:
print("Student {}".format(number_of_students[i]), "score is {}".format(grades_list_valid[i]), "and grade is C")
elif grade >= best_score - 40:
print("Student {}".format(number_of_students[i]), "score is {}".format(grades_list_valid[i]), "and grade is D")
else:
print("Student {}".format(number_of_students[i]), "score is {}".format(grades_list_valid[i]), "and grade is F")
i+=1
this the correct way,in your code i=3 which is why you are getting the same answer for each student

As Quinn said, your top loop iterates over i, which finishes at i = 3. Future references to i will yield 3.
Some things I noticed:
1) What you can do is check their grade at the same time as you loop through.
2) Additionally, you don't need to find the maximum each loop, you can get it once outside the loop and then reference it inside.
3) Finally, it looks quite ugly when you have all of these print statements, it makes it much nicer to read if you assign the grade in the if statements and then print once with the found grade, like so:
best_score = max(grade_list_valid)
for i in range(len(grades_list_valid)):
curr_score = grades_list_valid[i]
if(curr_score >= best_score - 10):
grade = "A"
...
print("Student {} score is {} and grade is {}".format(i, curr_score, grade))
There are some further small optimisations you can make as well. For example, the list comprehension you have:
[ int(x) for x in grades_list ]
Is the classic case for a map:
map(int, grades_list)

Related

PYTHON - how to pick the input with the best score

I am trying to figure out how to use the 2 out of 3 scores that were inputted. Please see the sample output below!
num_students = int(input("Enter the number of students: "))
scores = input(f"Enter {num_students} scores: ")
scores = [int(score) for score in scores.split()]
best_score = max(scores)
for i in range(num_students):
if scores[i] >= best_score - 10:
grade = "A"
elif scores[i] >= best_score - 20:
grade = "B"
elif scores[i] >= best_score - 30:
grade = "C"
elif scores[i] >= best_score - 40:
grade = "D"
else:
grade = "F"
print("Student", i, "score is", scores[i], "and grade is", grade)
For instance, if you were asked to input 2 scores but entered 3 instead, it would only pick the first 2 scores.
Also, when less scores are inputted than requested, it just asks to enter again. Please see examples below. Thank you!
students: 2
2 score(s) are: 20 50 60
Student 1 score is 20 and grade is B
Student 2 score is 50 and grade is A
students: 2
Enter 2 score(s): 30
Enter 2 score(s): 50 90
Student 1 score is 50 and grade is A
Student 2 score is 90 and grade is B

How to assign grade from a list in python

I am creating a program that takes users and stores them in list and takes their marks and afterwards it grades them. I've done the user input part and the marks as well along with the average of them but I am struggling to give them grade and print it along with their name so it will be like Name marks Grade. If anyone can help me with this I'll be thankful greatly here is my code
students=[]
for i in range (2):
x=(input("Enter Student Name. \n"))
students.insert(i,x)
i+=1
print(students)
grades = []
for student in students:
grade = eval(input(f"Enter the grade for {student}: "))
grades.append(grade)
result = list(zip(students, grades))
print(result)
average = sum(grades) / len(grades)
print ( "Average is: " + str(average))
total = sum(grades)
# print ("Total is: " + str(total))
print("Highest marks", max(list(zip(grades, students))))
print("Lowest marks", min(list(zip(grades, students))))
## To do assign grades to each according to their marks
I am struggling to give them grade and print it along with their name so it will be like Name marks Grade.
Look at the below - it uses zip and loop
names = ['Jack','Dan']
grades = [67,86]
def _get_grade(grade):
if grade < 50:
return 'C'
elif grade >= 50 and grade <= 75:
return 'B'
else:
return 'A'
for name,grade in zip(names,grades):
print(f'Name: {name} - Grade: {_get_grade(grade)}')

Having trouble on this Python homework problem

Question: Write a program to continuously asks the user an exam score given as integer percentages in the range 0 to 100. If a value not in the range is input except for -1, print out an error and prompt the user to try again. Calculate the average of all valid grades input along with the total number of grades in each letter-grade category as follows: 90 to 100 is an A, 80 to 89 is a B, 70 to 79 is a C, 60 to 69 is a D, and 0 to 59 is an F. Use a negative score as a sentinel value to indicate the end of the input. (The negative value is used only to end the loop, so do not use it in the calculations.) For example, if the input is.
#Enter in the 4 exam scores
g1=int(input("Enter an exam score between 0 and 100 or -1 to end: "))
g2=int(input("Enter an exam score between 0 and 100 or -1 to end: "))
g3=int(input("Enter an exam score between 0 and 100 or -1 to end: "))
g4=int(input("Enter an exam score between 0 and 100 or -1 to end: "))
total =(g1 + g2 + g3 + g4)
while g1 is range(0,100):
continue
else:
print("Sorry",g1,"is not in the range of 0 and 100 or -1. Try again!")
while g2 is range(0,100):
continue
else:
print("Sorry",g2,"is not in the range of 0 and 100 or -1. Try again!")
while g3 is range(0,100):
continue
else:
print("Sorry",g3,"is not in the range of 0 and 100 or -1. Try again!")
while g4 is range(0,100):
continue
else:
print("Sorry",g4,"is not in the range of 0 and 100 or -1. Try again!")
#calculating Average
def calc_average(total):
return total/4
def determine_letter_grade(grade):
if 90 <= grade <= 100:
1 + TotalA
elif 80 <= grade <= 89:
1 + TotalB
elif 70 <= grade <= 79:
1 + TotalC
elif 60 <= grade <= 69:
1 + TotalD
else:
1 + TotalF
grade=total
average=calc_average
#printing the average of the 4 scores
print("You entered four valid exam scores with an average of: " + str(average))
print("------------------------------------------------------------------------")
print("Grade Distribution:")
print("Number of A's: ",TotalA)
print("Number of B's: ",TotalB)
print("Number of C's: ",TotalC)
print("Number of D's: ",TotalD)
print("Number of F's: ",TotalF)
Sample output that I was given:
Enter an exam score between 0 and 100 or -1 to end: 88.64
Enter an exam score between 0 and 100 or -1 to end: 103
Sorry, 103 is not in the range of 0 and 100 or -1. Try Again!
Enter an exam score between 0 and 100 or -1 to end: 99.10
Enter an exam score between 0 and 100 or -1 to end: 71.52
Enter an exam score between 0 and 100 or -1 to end: 73
Enter an exam score between 0 and 100 or -1 to end: -1
You entered 4 valid exam scores with an average of 83.07.
Grade Distribution
Number of A’s = 1
Number of B’s = 1
Number of C’s = 2
Number of D’s = 0
Number of F’s = 0
Note: This is my first computer science class so I'm sure there is an obvious work around that I am missing but id appreciate any help I can get
Here is my walk-through explanation:
So, the program is supposed to ask the user what score they got until they say they got a score of -1, in which after you give them their results. To loop until they give -1, we can use a while loop:
inp = float(input("Enter an exam score between 0 and 100 or -1 to end: ")) # Get input
grades = []
while inp > -1: # Loop until user gives a score of -1
if inp >= 0 and inp <= 100: # Check if valid grade
grades.append(inp) # Add grade to grades list
inp = float(input("Enter an exam score between 0 and 100 or -1 to end: ")) # Ask again
else:
print("Sorry", inp, "is not in the range of 0 and 100 or -1. Try again!") # Invalid grade
# ANALYSIS OF GRADES
# Format first line of output - the first str(len(grades)) give the amount of grades they entered,
# and the str(sum(grades) / len(grades)) gives the average of the grades list.
print("You entered", str(len(grades)), "valid exam scores with an average of", str(sum(grades) / len(grades)))
print("Grade Distribution:")
print("Number of A's =", str(sum(90 <= g <= 100 for g in grades)) # I am using a very short notation
print("Number of B's =", str(sum(80 <= g <= 89 for g in grades)) # here - this is basically counting
print("Number of C's =", str(sum(70 <= g <= 79 for g in grades)) # the number of grades that are
print("Number of D's =", str(sum(60 <= g <= 69 for g in grades)) # a valid value based on the checks
print("Number of F's =", str(sum(0 <= g <= 59 for g in grades)) # I am making.
Hopefully my comments help you figure out what is happening in my code!
here your problem can be devided into few parts,
get number of exam from user
get the valid input from user for those exam
calculate the average of all exam
calculate the grade distribution
exit if user input is -1
below code is following all these steps
#calculating Average
def calc_average(scores):
return sum(scores)/len(scores)
grade_dist = {
(90, 101):'A',
(80,90):'B',
(70, 80):'C',
(59, 70):'D',
(0,59):'F'
}
def get_grade_freq(scores):
grades = {'A':0, 'B':0, 'C':0, 'D':0, 'F':0}
for score in scores:
for k, v in grade_dist.items():
if score in range(k[0], k[1]):
grades[v]+=1
print("Grade distributions")
for grade, number in grades.items():
print("Number of {}’s = {}".format(grade, number))
def get_scores(n):
scores = []
cond = True
while cond and n>0:
score = int(input("Enter an exam score between 0 and 100 or -1 to end : "))
if score==-1:
cond=False
return -1
if score not in range(0,101):
print("Sorry, {} is not in the range of 0 and 100 or -1. Try Again!".format(score))
if score in range(0,101):
scores.append(score)
n-=1
return scores
def main():
n = int(input('total number of exams ' ))
scores = get_scores(n)
if scores == -1:
exit(-1)
average = calc_average(scores)
print("You entered {} valid exam scores with an average of {}.".format(n, average))
get_grade_freq(scores)
if __name__=='__main__':
main()
Whenever you have multiple instances of similar things to manipulate (scoring ranges, total counts) you must try to use multi-value structures rather than individual variables. Python's lists and dictionaries are designed for collecting multiple entries either as a positional list or as a keyed index (dictionary).
This will make your code more generalized. You'll know you're on the right track when you manipulate concepts rather than instances.
For example:
grading = [(None,101),("A",90),("B",80),("C",70),("D",60),("F",0)]
scores = {"A":0, "B":0, "C":0, "D":0, "F":0}
counts = {"A":0, "B":0, "C":0, "D":0, "F":0}
while True:
input_value = input("Enter an exam score between 0 and 100 or -1 to end: ")
value = int(input_value)
if value == -1: break
score = next((s for s,g in grading if value >= g),None)
if score is None:
print("sorry ",input_value," is not -1 or in range of 0...100")
continue
scores[score] += value
counts[score] += 1
inputCount = sum(counts.values())
average = sum(scores.values())//max(1,inputCount)
print("")
print("You entered", inputCount, "valid exam scores with an average of: ", average)
print("------------------------------------------------------------------------")
print("Grade Distribution:")
for grade,total in counts.items():
print(f"Number of {grade}'s: ",total)
The grading list contains pairs of score letter and minimum value (in tuples). such a structure will allow you to convert the grade values in to score letters by finding the first entry that has a value lower or equal to the input value and use the corresponding letter.
The same list is used to validate the input value by strategically placing a None value after 100 and no value below zero. The next() function will perform the search for you and return None when no valid entry is present.
Your main program loop needs to continue until the input value is -1 but it needs to go through the input at least onces (typical of a repeat-until structure but there is only a while in Python). So the while statement will loop forever (i.e. while True) and will need to be arbitrarily broken when the exit condition is met.
To accumulate the scores, a dictionary (scores) is better suited than a list because a dictionary will allow you to access instances using a key (the score letter). This allows you to keep track of multiple scores in a single variable. The same goes for counting how many of each score were entered.
To get the average at the end, you simply need to sum up the values scores of the scores dictionary and divide by the count of of scores you added to the counts dictionary.
Finally to print the summary of score counts, you can leverage the dictionary structure again and only write one generalized printing line for all the score letters and totals.
This may work for you:
scores = {
"A": 0,
"B": 0,
"C": 0,
"D": 0,
"F": 0,
}
total = 0
count = 0
input_value = 0
while (input_value != -1) and (count < 4):
input_value = int(input("Enter an exam score between 0 and 100 or -1 to end: "))
if 0 <= input_value <= 100:
total += input_value
count += 1
if input_value >= 90:
scores["A"] += 1
elif input_value >= 80:
scores["B"] += 1
elif input_value >= 70:
scores["C"] += 1
elif input_value >= 60:
scores["D"] += 1
else:
scores["F"] += 1
else:
print("Sorry", input_value, "is not in the range of 0 and 100 or -1. Try again!")
print("You entered {} valid exam scores with an average of: {}".format(count, total / count))
print("------------------------------------------------------------------------")
print("Grade Distribution:")
print("Number of A's: ", scores['A'])
print("Number of B's: ", scores['B'])
print("Number of C's: ", scores['C'])
print("Number of D's: ", scores['D'])
print("Number of F's: ", scores['F'])

Python Grading Program

So I need to make a program that grades 10 students individually, then displays the average grade for all 10 students.
I think this is how the grading should look, but im not sure how to set up a count on the number of times its graded, or how to set up the average function. Help would be most welcome. I am a horrible coder.
score = int(input("Enter a score between 0 and 100: "))
if score >=89:
print("The grade is an A")
elif score>=79:
print("The grade is a B")
elif score>=69:
print("The grade is a C")
elif score>=59:
print("The grade is a D")
else:
print("The grade is a F")
You can try using a counter variable that goes from 0-9 and use a while loop to check and increment that counter value and after each loop calculates the average and keeps doing this till the last value has been entered
Counter = 0
average = 0
while (Counter <= 10):
score = int(input("Enter a score between 0 and 100: "))
if score >= 89:
print("The grade is an A")
elif score >= 79:
print("The grade is a B")
elif score >= 69:
print("The grade is a C")
elif score >= 59:
print("The grade is a D")
else:
print("The grade is a F")
Counter = Counter + 1
average = (score + average)
average = average/Counter
print("Average of all 10 students:",average)
So right now the code is configured specifically for just 10 loops but you can give the user the power to determine this by suggesting a value to end the loop and the while loop will check for this value and when the loop sees the value it exits the loop and gives a value
Also with each loop there is a counter value that keeps increasing and an average value that holds the sum of the values entered and when the loop exits and average is calculated by dividing the sum by the counters and this gives the results
This should do the trick.
total = 0
for i in range(10):
score = int(input("Enter a score between 0 and 100: "))
if score >= 89:
print("The grade is an A")
elif score >= 79:
print("The grade is a B")
elif score >= 69:
print("The grade is a C")
elif score >= 59:
print("The grade is a D")
else:
print("The grade is a F")
total += score
print("Average of all 10 students:", total/10)
In the for loop you get the score of each student and then add it to the total of all students. When the loop ends you divide it with the total number of students so 10.
total score / total number of students total / 10
You can define a function that finds the average score. Store all the scores in a list and then pass the list as an argument in the function
def avg(scores): #assuming scores is the name of the list
avg = sum(scores)/len(scores)
return "Average score is {}".format(avg)
Or
return f'Average score is {avg}' #for python3
Not sure I understand what you mean by number of times it is graded but I think you can include a while loop and a variable that increases by 1 every time it grades.

Why is this always printing the first if statement and nothing else?

grade = raw_input("What was your score?")
if grade >= 93:
print "For a score of " + grade + ", your grade is an A"
elif grade >= 90 and grade < 93:
print "For a score of " + grade + ", your grade is an A-"
elif grade >= 87 and grade < 90:
print "For a score of " + grade + ", your grade is a B+"
elif grade >= 83 and grade < 87:
print "For a score of " + grade + ", your grade is a B"
elif grade >= 80 and grade < 83:
print "For a score of " + grade + ", your grade is a B-"
elif grade >= 77 and grade < 80:
print "For a score of " + grade + ", your grade is a C+"
elif grade >= 73 and grade < 77:
print "For a score of " + grade + ", your grade is a C"
elif grade >= 70 and grade < 73:
print "For a score of " + grade + ", your grade is a C-"
elif grade >= 67 and grade < 70:
print "For a score of " + grade + ", your grade is a D+"
elif grade >= 63 and grade < 67:
print "For a score of " + grade + ", your grade is a D"
elif grade >= 60 and grade < 63:
print "For a score of " + grade + ", your grade is a D-"
else:
print "For a score of " + grade + ", your grade is an F"
No matter what is entered as raw input, the statement printed is always "For a score of ___, your grade is an A" even if it should be a B or a D or anything else
raw_input returns a string, not a number. Before the comparison, you need to turn it into int or float.
Btw, if you are starting with python, go for 3 instead of 2. 2 is already EOL and support for libraries is starting to decrease.
You are comparing an integer and a string.
You need to cast the string to an integer using int().
So, you could for example do something like this
grade = int(raw_input("What was your score?"))
Of course, this would then leave you with the problem that that (ugly) concatenation you are doing to display your output message would stop working (as you cannot concatenate strings and integers).
Rather than directly using string concatenation, it's 99% of the times better to use format, like this:
print "For a score of {}, your grade is an A".format(grade)
grade = int(input("Enter your score"))
use python 3.

Categories