Finding A Collective Average & Letter Grade For Tests & Assignments - python

I am using Python 3.4.1 and I am trying to write a code that does the following:
class Student(object):
def __init__(self, name):
self.name, self.grades = name, []
def append_grade(self, grade):
self.grades.append(grade)
def average(self):
return sum(self.grades) / len(self.grades)
def letter_grade(self):
average = self.average()
for value, grade in (90, "A"), (80, "B"), (70, "C"), (60, "D"):
if average >= value:
return grade
else:
return "F"
def main():
print()
a_class = [] # "class" by itself is a reserved word in Python, avoid using
while True:
print()
print('{} students in class so far'.format(len(a_class)))
another_student = input('Do you have another student to enter (y/n) ? ')
if another_student[0].lower() != 'y':
break
print()
student_name = input('What is the student\'s ID? ')
a_class.append(Student(student_name))
print()
print('student :', student_name)
print('------------------------------------------------')
number_of_tests = int(input('Please enter the number of tests : '))
for test_num in range(1, number_of_tests+1):
print('test grade {}'.format(test_num), end='')
score = float(input(' : '))
if score < 0: # stop early?
break
number_of_assignments = int(input('Please enter the number of assignments : '))
for assignment_num in range(1, number_of_assignments+1):
print('assignment grade {}'.format(assignment_num), end='')
score2 = float(input(' : '))
if score2 < 0: # stop early?
break
number_of_participation = int(input('Please enter 1 to add participation grade : '))
for participation_num in range(1, number_of_participation+1):
print('participation grade {}'.format(participation_num), end='')
score3 = float(input(' : '))
if score3 < 0: # stop early?
break
a_class[-1].append_grade(score + score2 + score3) # append to last student added
print_report(a_class)
def print_report(a_class):
print()
print('Student Grades')
print()
for student in sorted(a_class, key=lambda s: s.name):
print('student: {:20s} average test score: {:3.2f} grade: {}'.format(
student.name, student.average(), student.letter_grade()))
print()
print('The class average is {:.2f}'.format(class_average(a_class)))
def class_average(a_class):
return sum(student.average() for student in a_class) / len(a_class)
main()
The task here is to get the letter grade of a student by adding 3 different things and getting the average. I need to be able to input the test scores, assignment scores, and 1 participation grade. Those need to average out and give me a final letter grade. I was able to find out how to do just one set of scores to average but when I added the other scores, the average is wrong. What can I edit here?

I didn't look in great detail, but this:
a_class[-1].append_grade(score + score2 + score3)
...makes me suspect that you are adding a single value to the list of grades, that is above 100%. That might account for your averages being too high.
Instead, you likely should:
a_class[-1].append_grade(score)
a_class[-1].append_grade(score2)
a_class[-1].append_grade(score3)

Related

How to define a function that can take more than 1 input from user?

# function to calculate average marks of the list
def average_marks(marks):
total_sum_of_scores = sum(marks)
total_num_of_sub = len(marks)
average_marks = total_sum_of_scores / total_num_of_sub
return average_marks
# funtion to compute grade based on average_marks
def compute_grade(average_marks):
if average_marks >= 80:
grade = "A"
elif average_marks >= 60:
grade = "B"
elif average_marks >= 50:
grade = "C"
else:
grade = "F"
return grade
marks = [75,77,94,78,83,86,72]
average_marks = average_marks(marks)
grade = compute_grade(average_marks)
print("Your result is: ",average_marks , "and your grade is:", grade)
Instead of using a predefined list. I want to take input from users. Users will enter number and when "done" is entered, the programme is terminated. Below is what i have tried but no luck.
def marks():
n = int(input("Enter your number"))
marks = []
for i in range(n):
element = int(input("Please enter students score: "))
marks.append(element)
result = marks
print(marks)
marks()
Try this:
marks = input("Please enter your scores: ").split()

Python if elif and loops

I wrote this for my beginner class and I don't know how to get the NAME of the SECOND STUDENT with the 2nd highest score. After testing it, I believe the code works for the first student.
I think what I need is to store the highest score in to variable high_score and then the next highest in to second_score and then compare the third score to both the highest and second score. But I am confused on how to get the name of the second highest scoring student.
num_students = int(input("enter number of students: "))
high_score = 0
high_name = ""
second_name = ""
second_score = 0
for i in range(1,num_students + 1):
if num_students < 2:
break
if num_students >= 2:
name = input("enter student name: ")
score = int(input("enter student score: "))
if score > second_score:
if score > high_score:
second_score = high_score
high_score = score
high_name = name
elif score < high_score:
second_score = score
second_name = name
print()
print("Top Two Students")
print()
print(high_name,"'s score is", high_score)
print(second_name,"'s score is", second_score)
In addition to Gary02127's solution, I'd like to point out a few other improvements:
You should move if num_students < 2 outside of your loop. It would be enough to check the condition once after the user inputted the number of students.
You could also write for i in range(num_students). It doesn't matter if the range starts with 0 or 1 since you are not using i.
Also, if you are not using a variable, you could use _ (throwaway variable) instead. See more about for _ in range(num_students) here: What is the purpose of the single underscore "_" variable in Python?.
Instead of:
if score > second_score:
if score > high_score:
# ...
else:
# ...
You could also write:
if high_score < score:
# ...
elif second_score < score:
# ...
Here is a verbose solution considering suggested improvements:
num_students = int(input("Enter number of students: "))
if num_students < 2:
exit()
highest_name = None
highest_grade = 0
second_highest_name = None
second_highest_grade = 0
for _ in range(num_students):
name = input("Enter student's name: ")
grade = int(input("Enter student's score: "))
if highest_grade < grade:
second_highest_name = highest_name
second_highest_grade = highest_grade
highest_name = name
highest_grade = grade
elif second_highest_grade < grade:
second_highest_name = name
second_highest_grade = grade
print(highest_name, highest_grade) # highest grade
print(second_highest_name, second_highest_grade) # second highest grade
You could also use a list and sorted() (built-in function):
from operator import itemgetter
num_students = int(input("Enter number of students: "))
if num_students < 2:
exit()
grades = []
for _ in range(num_students):
name = input("Enter student's name: ")
grade = int(input("Enter student's score: "))
grades.append((name, grade))
grades = sorted(grades, key=itemgetter(1), reverse=True)
print(grades[0]) # highest grade
print(grades[1]) # second highest grade
You could also use a specialized list such as SortedList (requires external package):
from sortedcontainers import SortedList
num_students = int(input("Enter number of students: "))
if num_students < 2:
exit()
grades = SortedList(key=lambda record: -record[1])
for _ in range(num_students):
name = input("Enter student's name: ")
grade = int(input("Enter student's score: "))
grades.add((name, grade))
print(grades[0]) # highest grade
print(grades[1]) # second highest grade
Notes:
Difference between sorted() and str.sort(). sorted() creates a new sorted list whereas str.sort() modifies the current list.
itemgetter(1) is equals to lambda record: record[1].
You can install SortedList with: pip install sortedcontainers.
Here's a solution based on my previous comments to your original post.
num_students = int(input("enter number of students: "))
high_score = 0
high_name = ""
second_name = ""
second_score = 0
for i in range(1,num_students + 1):
if num_students < 2:
break
# if num_students >= 2: # don't need this "if" after previous "break"
name = input("enter student name: ")
score = int(input("enter student score: "))
if score > second_score:
if score > high_score:
second_score = high_score
second_name = high_name # NEW
high_score = score
high_name = name
else: # simplified to just a plain "else:"
second_score = score
second_name = name
print()
print("Top Two Students")
print()
print(high_name,"'s score is", high_score)
print(second_name,"'s score is", second_score)
Notice that simplifying that last "elif ...:" to a simple "else:" also solves a simple bug where entering the current high score again can be ignored and not captured. If you were to run your code as is and use input values "100 80 100", you would find the 2nd high score set to 80 instead of 100.
You can simply store the details in a list. And use list.sort() to sort the values according to the score.
Here is the working code:
num_students = int(input("Enter number of students: "))
scores = []
if num_students < 2:
print('Number of students less than 2')
exit()
for i in range(num_students):
name = input("Enter student's name: ")
score = int(input("Enter student's score: "))
scores.append([name, score])
scores.sort(key=lambda details: details[1], reverse=True)
print("Top Two Students")
print()
print(f"{scores[0][0]}'s score is {scores[0][1]}")
print(f"{scores[1][0]}'s score is {scores[1][1]}")

Wanting to input bowling scores, total, average them

Need for a user to input bowling scores and store them, to be totaled and averaged later and they can press "q" or "Q" to quit and total/average them. I've tried fumbling around figuring out loops but not sure how to deal with inputting integers and also accepting "Q" to stop loop. Thanks for any help.
nums = []
scores = ""
while scores != 'q'.lower():
scores = input("Please enter a score (xxx) or 'q' to exit: ")
if scores != 'q':
nums.append(int(scores))
elif scores == 'q'.lower():
print("quitting")
break
scores = int()
def Average(nums):
return sum(nums) / len(nums)
total = sum(nums)
print(f"The total score is: {total}")
average = Average(nums)
print("The score average is: ", round(average, 2))
Getting error:
Traceback (most recent call last):
File "/Users/ryaber/PycharmProjects/pythonProject/main.py", line 11, in
scores = input("Please enter a score (xxx) or 'q' to exit: ")
File "", line 1, in
NameError: name 'q' is not defined
So not sure how to allow it to accept "Q" to stop loop and total/average them.
Remove .lower() in q.lower() and move it and make it to score.lower().
So if user types in q or Q both will be accepted as quit
You do not need average function or while scores != 'q' instead you could change it to something simple
So complete code -
nums = []
scores = ""
while True:
scores = input("Please enter a score (xxx) or 'q' to exit: ")
if scores.lower() != 'q':
nums.append(int(scores))
elif scores.lower() == 'q':
print("quitting")
break
scores = int()
total = sum(nums)
print(f"The total score is: {total}")
average = total/len(nums)
print("The score average is: ", round(average, 2))
Result:
Please enter a score (xxx) or 'q' to exit: 25
Please enter a score (xxx) or 'q' to exit: 32
Please enter a score (xxx) or 'q' to exit: Q
quitting
The total score is: 57
The score average is: 28.5
Edit -
While this may be complicated, this will solve your problem -
nums = []
scores = ""
while True:
scores = input("Please enter a score (xxx) or 'q' to exit: ")
try: # This will run when scores is a number
scores = int(scores)
if scores.lower() == type(0):
nums.append(int(scores))
except: # Will run when it is a alphabet
if scores.lower() == 'q':
print("quitting")
break
else:
continue
scores = int()
total = sum(nums)
print(f"The total score is: {total}")
average = total/len(nums)
print("The score average is: ", round(average, 2))
break
nums.append(int(scores))
just cast it to an int ...
You only need to convert your input string to an int before storing it:
nums = []
scores = ""
while scores != 'q'.lower():
scores = input("Please enter a score (xxx) or 'q' to exit: ")
if scores != 'q':
nums.append(int(scores))
elif scores == 'q'.lower():
print("quitting")
break
def Average(nums):
return sum(nums) / len(nums)
total = sum(nums)
print(f"The total score is: {total}")
average = Average(nums)
print("The score average is: ", round(average, 2))
You need to append integral value of score to the list
nums.append(int(scores))
Also, I guess you might want to use a f-string here
print(f"The total score is: {total}")
EDIT :
if scores.lower() != 'q':
nums.append(int(scores))
elif scores.lower() == "q":
print("quitting")
break
As pointed out by #PCM, you need to use the .lower() method on the variable
The final working code :
nums = []
scores = ""
while scores != 'q':
scores = input("Please enter a score (xxx) or 'q' to exit: ")
if scores.lower() != 'q':
nums.append(int(scores))
elif scores.lower() == "q":
print("quitting")
break
scores = int()
def Average(nums):
return sum(nums) / len(nums)
total = sum(nums)
print(f"The total score is: {total}")
average = Average(nums)
print("The score average is: ", round(average, 2))
You can read more about f-strings here

Validate the score in python

array = []
total = 0
text = int(input("How many students in your class: "))
print("\n")
while True:
for x in range(text):
score = int(input("Input score {} : ".format(x+1)))
if score <= 0 & score >= 101:
break
print(int(input("Invalid score, please re-enter: ")))
array.append(score)
print("\n")
print("Maximum: {}".format(max(array)))
print("Minimum: {}".format(min(array)))
print("Average: {}".format(sum(array)/text))
I tried to make a python program, to validate the score, but it's still a mistake, I want to make a program if I enter a score of less than 0 it will ask to re-enter the score as well if I input more than 100. Where is my error?
Change the if statement:
array = []
total = 0
text = int(input("How many students in your class: "))
print("\n")
for x in range(text):
score = int(input("Input score {} : ".format(x+1)))
while True:
if 0 <= score <= 100:
break
score = int(input("Invalid score, please re-enter: "))
array.append(score)
print("\n")
print("Maximum: {}".format(max(array)))
print("Minimum: {}".format(min(array)))
print("Average: {}".format(sum(array)/text))
Here, the score at the same time can't be less than 0 and greater than 100. So as you want to break of the score is between 0 and 100, we use 0 <= score <= 100 as the breaking condition.
Also the loops were reversed, since you won't get what you expected to.
try this one:
array = []
total = 0
num_of_students = int(input("How many students in your class: "))
print("\n")
for x in range(num_of_students):
score = int(input("Input score {} : ".format(x + 1)))
while True:
if score < 0 or score > 100:
score = int(input("Invalid score, please re-enter: "))
else:
array.append(score)
break
print("\n")
print("Maximum: {}".format(max(array)))
print("Minimum: {}".format(min(array)))
print("Average: {}".format(sum(array)/num_of_students))
I renamed some of your variables. You should always try to using self explanatory variable names. I am also using string interpolation (should be possible for Python +3.6) and comparison chaining.
score_list = []
total = 0
number_of_students = int(input("How many students in your class: "))
print("\n")
for student in range(number_of_students):
score_invalid = True
while score_invalid:
score_student = int(input(f"Input score {student + 1} : "))
if (0 <= score_student <= 100):
score_invalid = False
else:
score_invalid = True
if score_invalid:
print("Invalid score!\n")
score_list.append(score_student)
print("\n")
print(f"Maximum: {max(score_list)}")
print(f"Minimum: {min(score_list)}")
print(f"Average: {sum(score_list) / number_of_students}")
You could try something like this:
score = -1
first_time = True
while type(score) != int or score <= 0 or score >= 101 :
if first_time:
score = int(input("Input score: "))
first_time = False
else:
score = int(input("Invalid score, please re-enter: "))
array.append(score)

TypeError: unsupported operand type(s) for /: 'str' and 'int' in python

I am working on a project for finding students grade average for 3 exams.
Everything seems fine with my work but one error I am receiving with the following line:
student_avg = ((firstterm) +str (midterm) +str (final)) / 3
The program is an instructor's companion app. My professor told me to do 1st term mid term and final for 5 subjects.
After one week of working I still faced some problems on that.
Can anyone review my code and see what my mistake is?
def determine_score(grade):
if 95<= grade <=100:
return 'A+'
elif 91<= grade <=96:
return 'A'
elif 89<= grade <=92:
return 'A-'
elif 85<= grade <=90:
return 'B+'
elif 81<= grade <=86:
return 'B'
elif 79<= grade <=82:
return 'B-'
elif 75<= grade <=80:
return 'C+'
elif 72<= grade <=76:
return 'C'
elif 64<= grade <=73:
return 'D'
elif 0<= grade <=65:
return 'F'
else:
return 'invalide score'
def firstTerm():
fst_sub1=int(input("Enter first term marks of the first subject: "))
fst_sub2=int(input("Enter first term marks of the second subject: "))
fst_sub3=int(input("Enter first term marks of the third subject: "))
fst_sub4=int(input("Enter first term marks of the fourth subject: "))
fst_sub5=int(input("Enter first term marks of the fifth subject: "))
firsttermScore = (fst_sub1+fst_sub2+fst_sub3+fst_sub4+fst_sub5)/5
return 'firsttermScore'
def midTerm():
mid_sub1=int(input("Enter mid term marks of the first subject: "))
mid_sub2=int(input("Enter mid term marks of the second subject: "))
mid_sub3=int(input("Enter mid term marks of the third subject: "))
mid_sub4=int(input("Enter mid term marks of the fourth subject: "))
mid_sub5=int(input("Enter mid term marks of the fifth subject: "))
midtermScore = (mid_sub1+mid_sub2+mid_sub3+mid_sub4+mid_sub5)/5
return 'midtermScore'
def final():
fnl_sub1=int(input("Enter final marks of the first subject: "))
fnl_sub2=int(input("Enter final marks of the second subject: "))
fnl_sub3=int(input("Enter final marks of the third subject: "))
fnl_sub4=int(input("Enter final marks of the fourth subject: "))
fnl_sub5=int(input("Enter final marks of the fifth subject: "))
finalScore = (fnl_sub1+fnl_sub2+fnl_sub3+fnl_sub4+fnl_sub5)/5
return 'finalScore'
total = 0
highest = 0
numStudents = int (input("How Many Students are there? "))
while numStudents < 0 or numStudents > 100:
numStudents = int (input("Please enter a number between 0 and 100? "))
for i in range (numStudents):
student_name = (input("Enter Student's Name Please: "))
firstterm = firstTerm()
midterm = midTerm()
final = final()
student_avg = ((firstterm) +str (midterm) +str (final)) / 3
if (highest < student_avg):
highest = student_avg
grade = student_avg
winner = student_name
list_marks = []
list_marks.append([student_name, student_avg,])
print ("exam result: ", list_marks, "grade is: ", determine_score(grade))
print ("The Student with the higgest average is: ", winner, "With the highest average of: ", highest, "gpa is: " + determine_score(grade) )
In your final print statement, you need to make sure that everything is a string:
print ("The Student with the higgest average is: ", winner, "With the highest average of: ", str(highest), "gpa is: " + determine_score(grade) )
Also your functions should return the value and not a hardcoded string:
return firsttermScore
...
return midtermScore
...
return finalScore
You also need to operate on double (or float) if you want a precise score:
firsttermScore = (fst_sub1+fst_sub2+fst_sub3+fst_sub4+fst_sub5)/5.0
finalScore = (fnl_sub1+fnl_sub2+fnl_sub3+fnl_sub4+fnl_sub5)/5.0
midtermScore = (mid_sub1+mid_sub2+mid_sub3+mid_sub4+mid_sub5)/5.0
student_avg = (firstterm + midterm + final) / 3.0
If you divide by an int, and your input data are int. The result will be an int, and you will lose your precision.
And a last print statement that would fail because list_marks is a list and not a string:
print ("exam result: ", str(list_marks), "grade is: ", determine_score(grade))
There is also a last error:
finalGrade = final()
You need to echange the name of your variable to something different from your function.

Categories

Resources