Grading Scale in Python Without Decision Statements - python

I am trying to create a program in python 3 that will take a percentage score and print out the letter grade based on the grading scale 90-100:A,80-89:B,70-79:C,60-69:D,<60:F using strings and lists
#gradeScale.py
#This program takes a percent score and tells the user what letter grade it is based on the grading scale
def main():
print("This program takes a percent score and tells the user what letter grade it is based on the grading scale")
gradingScale = ["F","F","F","F","F","F","F","D","C","B","A"]
grade = eval(input("Please enter the percent score: "))
main()

You've got a great start:
gradingScale = ["F", "F", "F" , "F" , "F" , "F", "F", "D", "C", "B", "A"]
This is a list of 11 letter grades. Your scores range from 0 to 100. How might you map a range of 101 possible grades (0 to 100) to those items? Maybe by dividing by 10 and throwing away the remainder:
print(gradingScale[grade // 10])
This doesn't work quite right though: 70 should be a C but comes out as D. 99 should be an A but comes out as B. Only 100 comes out as A when 90-100 should be A.
The answer here is that there are two "bins" of 10 that should be an A. 90-99, and 100-109 (although we will only use 100 out of that bin). So, we just need to shift things down: take one of the Fs off the start and add an A to the end of the grading scale:
gradingScale = ["F", "F" , "F" , "F" , "F", "F", "D", "C", "B", "A", "A"]
And now it works!
To simplify the code a little, we can take advantage of the fact that the letter grades are single characters, and also that strings can be indexed like lists (you get a single character) and so gradingScale can just be a simple string:
gradingScale = "FFFFFFDCBAA"

Sorry for using magic out of Hogwarts but:
grades = 'FEDCBA'
score = int(input('Enter your score: '))
grade = ((score // 10) - 4) * (score // 50) * (100 // (score + 1)) + (score // 100) * 5
print('Grade is', grades[grade])
works from 0 to 199 (90-199 is an A)
I'll try to explain 3rd line.
(score // 10) - 4) helps us find grade from 50 to 99 as index in grades string.
* (score // 50) makes all scores from 0 to 49 evaluate to 0 (index of 'F')
* (100 // (score + 1)) + (score // 100) * 5 makes all scores from 100 to 199 evaluate to 5 (index of 'A')

Edit:
Okay, since this is apparently a homework assignment, and you have only learned these topics so far ("loops, graphics, lists, strings, some of the math library, and other extremely basic things like print statements"), we will try something else.
I will leave this answer here in case you want to come back and study it once you've learned about dictionaries, but see the answers of #kindall and #Yevhen Kuzmovych below! Good work thus far.
As I alluded to in the comments, since you can't use if, elif, or else control flow statements, it looks like a dict lookup should suit you:
def main():
grades = {'A': range(90, 101), 'B': range(80, 90), 'C': range(70, 80), 'D': range(60, 70), 'F': range(0, 60)}
grade = eval(input("Please enter the percent score: "))
return [letter for letter, rnge in grades.items() if grade in rnge][0]
Breaking it down:
grades = {'A': range(90, 101), 'B': range(80, 90), 'C': range(70, 80), 'D': range(60, 70), 'F': range(0, 60)}
This is a dictionary, in which your designated letter grades are keys and their respective upper and lower bounds are range objects.
[letter for letter, rnge in grades.items() if grade in rnge][0]
This is a list comprehension, in which we iterate through each (key, value) tuple in the list returned by grades.items() and see if the submitted grade falls in the range of a given letter grade. Since there is no overlap in the ranges, this list will have one element. The [0] indexing at the end allows us to return str instead of a list.
Try it:
>>> main()
Please enter the percent score: 80
'B'

You could use a string and just look up the grade by index.
grades = ("F" * 60) + ("D" * 10) + ("C" * 10) + ("B" * 10) + ("A" * 11)
def get_grade(score):
return grades[score]
def main():
print("This program takes a percent score and tells the user what letter grade it is based on the grading scale")
grade = get_grade(input("Please enter the percent score: "))
print(grade)
main()

Illustrating a program that provides a grade for a score:
def main():
print "Provides a grade as per the range of marks"
score=input("Enter the exam score: ")
gr="FFFFFFDCBAA"
pos=gr[score/10]
print "The grade obtained is: ",pos
main()

Related

Averaging grade scores in python?

for some reason when I average the scores, it's not the right answer i.e usually something like 2 percent or 540, even if that's not what the arithmetic answer would be. Sometimes it works, sometimes it doesn't! As well, code runs in VS, but displays syntax error in IDLE. I have no idea if they're related, but in any case, I have no idea how to fix it. Any help is appreciated!
number=1
quiz=1
mini=1
peer=1
sum=0
while number <51:
assignment = int(input("What's your grade for assignment "+ str(number) + "?"))
number = number + 1
sum += assignment
assigns = (sum // 500)*100
assigns2 = round(assigns, 2)
while peer <4:
peers = int(input("What is your grade for peer assignment "+ str(peer) + "?"))
peer = peer + 1
sum += peers
while quiz <11:
quizzes = int(input("What's your grade for quiz "+ str(quiz) + "?"))
quiz = quiz + 1
sum += quizzes
quiznos = (sum // 100)*100
quiznos2 = round(quiznos, 2)
while mini <11:
minisss = int(input("What is your grade for mini-project "+ str(mini) + "?"))
mini = mini + 1
sum += minisss
miniz = (sum // 200)*100
miniz2 = round(miniz, 2)
final = int(input("What was your score on the final? "))
print("CALCULATING YOUR GRADE...")
gradez = (sum/1200)*100
grader = round(gradez, 2)
print("*******")
print("The total possible points was 1100, and your total is",sum,"points! Your grade is", grader, "percent!")
print("*******")
if grader >= 90:
print("You've gotten an A!")
elif grader >= 80:
print("You've gotten a B!")
elif grader >= 70:
print("You've gotten a C!")
elif grader >= 60:
print("That's a D, sorry man!")
elif grader >= 0:
print("You've failed the class...")
print("*******")
print("You got a", assigns2, "percent for assignments!")
print("*******")
print("You got a", quiznos2, "percent for quizzes!")
print("*******")
print("You got a", miniz2, "percent for mini projects!")
print("*******")
examity = (final / 300)*100
examity2 = round(examity, 2)
print("Your final was", final, "out of 300, for a grade of", examity2, end="!")
For calculating the percent score for assignments, quizzes, and mini-projects, you are using the same sum variable. This means that your test scores are still added into the sum variable when you are calculating the quiz score, and the quiz and test scores are added into the sum when calculating the mini-projects score, leading to inflated scores. In short, you are using the sum variable in two conflicting ways - both to count up the total number of points and to store the separate sum values for each specific section. If I were you, I would create a separate total points variable and possibly separate sum variables with different names for each section (or reset the sum variable to 0 for each section). Also, I think you may be missing the final score in your total sum when you calculate the student's overall grade, and when calculating that total grade, you divide by 1200 but you say the total max points is 1100, and I'm not really sure how the peer assignments work into the overall score.
For the syntax error, it could be because of the versions of Python you are running in your different environments. If so, it may have to do with the end parameter in your last print statement. This article could be useful: Python SyntaxError: invalid syntax end=''.

Edhesive 7.5 code practice GPA average Python

Currently my code is:
def GPAcalc(grade, weighted):
grade = grade.lower()
dictionary = {"a": 4, "b": 3, "c": 2, "d": 1, "f": 0}
if weighted == 1 and grade in dictionary:
return "Your GPA score is: "+str(dictionary[grade] + 1)
elif weighted == 0 and grade in dictionary:
return "Your GPA score is: "+str(dictionary[grade])
else:
return "Invalid"
def GPAav():
grade = GPAcalc()
for i in range(0,cl):
grad= GPAcalc(grade,dictionary)
total = grade + total
print(total/cl)
cl = int(input("How many Classes are you taking? "))
for i in range(0,cl):
print(GPAcalc(input("Enter your letter Grade: "), int(input("Is it weighted?(1= yes, 0= no) "))))
GPAav()
I have to find the average GPA in decimal form from the rest of the code and output it. How would I go about getting the values from GPAcalc and using it in GPAav so i can average it out?
You have 2 options here. Store the grades in an list as they are entered or do the calculations on the fly. I chose the first option. This allows you to use the data later, if you want to add features the the app. You may also want to store the un-weighted grades in a list of tuples ([('a',True),('b',False)...]), but I just store the weighted grades.
Also, it is probably easier if you verify that the user is inputting the correct values as you read them. Have them keep re-trying until they get it right.
Your calculation functions should not print anything. They should just do the calculations they are required to do and return the result as a number.
grade_map = {"a": 4, "b": 3, "c": 2, "d": 1, "f": 0}
def GPAcalc(grade, weighted):
# Data has already been sanitized, so no error checks needed
return grade_map[grade] + weighted
def GPAav(grades):
return sum(grades) / len(grades)
def input_grades():
# TODO: Make sure user enters a number
cl = int(input("How many classes are you taking? "))
grades = []
for _ in range(cl):
# Loop until valid input
while True:
# Get input and convert to lower case
grade = input("Enter your letter grade: ").lower()
if grade in grade_map:
# Ok data. Exit loop.
break
# This only prints on bad input
print("Invalid input. Enter a,b,c,d or f. Try again...")
# Loop until valid input
while True:
# Read the value as a string first to verify "0" or "1"
weighted = input("Is it weighted?(1= yes, 0= no) ")
if weighted in "01":
# Verified. Now convert to int to avoid an exception
weighted = int(weighted)
break
print("Invalid input. Enter 0 or 1. Try again...")
# Store weighted numeric grade in list
grades.append(GPAcalc(grade, weighted))
return grades
grades = input_grades()
print(f"Your average GPA is {GPAav(grades)}.")
TODO: The repeated code in input_grades() is a red-flag that maybe that code can be moved into a re-usable function.

Why is each grade inputted the same no matter what the program defines including the average?

The program is as follows: Write a program that asks the user to input 5 test scores. The program should display a letter grade for each score and the average test score.
I am having issues with my output showing me a letter grade of the first inputted grade for every grade including the average. My numeric average is also being outputted as a letter grade, but it gives the correct average letter for that rather than the correct numeric result for the grade. I am in a low level coding class, therefore the program must be written in this format.
Here is the code:
a=float(input("Enter score 1:"))
b=float(input("Enter score 2:"))
c=float(input("Enter score 3:"))
d=float(input("Enter score 4:"))
e=float(input("Enter score 5:"))
def determine_grade(a,b,c,d,e):
num=a
if(num<=100 and num>=90):
grade='A'
elif(num<=89 and num>=80):
grade='B'
elif(num<=79 and num>=70):
grade='C'
elif(num<=69 and num>=60):
grade='D'
else:
grade='F'
return grade
def calc_average(a,b,c,d,e):
mean=(a+b+c+d+e)//5
if mean<=100 and mean>=90:
avggrade='A'
elif(mean<=89 and mean>=80):
avggrade='B'
elif(mean<=79 and mean>=70):
avggrade='C'
elif(mean<=69 and mean>=60):
avggrade='D'
else:
avggrade='F'
return avggrade
grade=determine_grade(a,b,c,d,e)
avggrade=determine_grade(a,b,c,d,e)
mean=calc_average(a,b,c,d,e)
determine_grade(a,b,c,d,e)
calc_average(a,b,c,d,e)
print("Score Numeric Grade Letter Grade")
print("--------------------------------------------")
print("Score 1: ",a," ",grade)
print("Score 2: ",b," ",grade)
print("Score 3: ",c," ",grade)
print("Score 4: ",d," ",grade)
print("Score 5: ",e," ",grade)
print("--------------------------------------------")
print("Average Score: ",mean," ",avggrade)
Whenever I put in (a):
num=a,b,c,d,e
in place of what is shown in the code, I get a syntax error saying:
TypeError: '<=' not supported between instances of 'tuple' and 'int'
If I don't do what has been shown in (a), my output is this:
Enter score 1:90
Enter score 2:88
Enter score 3:76
Enter score 4:68
Enter score 5:40
Score Numeric Grade Letter Grade
--------------------------------------------
Score 1: 90.0 A
Score 2: 88.0 A
Score 3: 76.0 A
Score 4: 68.0 A
Score 5: 40.0 A
--------------------------------------------
Average Score: C A
Okay, so there's some things to talk about here. First, I suggest that you experiment a bit more with simpler functions to properly get used to them. When you define determine_grade(a,b,c,d,e) your function will expect to find a,b,c,d,e arguments inside the function, but if you read it again, you'll notice that you only mention a. This means when you call grade=determine_grade(a,b,c,d,e) you're only calculating a's grade, and that's why you have the same grade for everyone (if you type grade with your code you'll notice it will output 'A'.
Another way to write a function that does exactly what you're looking for is this:
def determine_grade(score):
num=score
if(num<=100 and num>=90):
grade='A'
elif(num<=89 and num>=80):
grade='B'
elif(num<=79 and num>=70):
grade='C'
elif(num<=69 and num>=60):
grade='D'
else:
grade='F'
return grade
You input a score (that can be a,b,c,d or e) and it calculates a grade. If you want to get everyone's grade, then you can do something like this:
grades=[]
for i in [a,b,c,d,e]:
grades.append(determine_grade(i))
This will bring a list with all grades.
Then, if you want the average grade, it's better to calculate the average score, so you can use your same function to get the grade:
mean_score=np.array([a,b,c]).mean()
mean_grade(determine_grade(mean_score)
Doing this you'll have all the information you need with way less lines of code (And you can make it even more efficient using list comprehensions, but that's a bit more advanced).
To answer your question, your functions should be rewritten to accept a single input and then called several times. Also, your program is a classic case of something that should be DRYed up (Don't Repeat Yourself). Instead of manually typing a = input(), b = input() why not consider just tossing all these inputs into a list (perhaps with some string formatting on your prompt like my code). Below is a program that can easily be adjusted to accept arbitrary amounts of inputs:
input_scores = [] # make our list
scores_input = 5 # tell the program we have 5 scores to record
for input_count in range(1, scores_input + 1):
input_scores.append(float(input("Enter score {}:".format(input_count))))
def determine_grade(percent): # single input
if 90 <= percent <= 100:
grade = 'A'
elif 80 <= percent <= 89:
grade = 'B'
elif 70 <= percent <= 79:
grade = 'C'
elif 60 <= percent <= 69:
grade = 'D'
else:
grade = 'F'
return grade # single output
def calc_average(local_score_list): # expects the list we made earlier (many inputs)
mean = sum(local_score_list) // len(local_score_list)
if 90 <= mean <= 100:
average_grade = 'A'
elif 80 <= mean <= 89:
average_grade = 'B'
elif 70 <= mean <= 79:
average_grade = 'C'
elif 60 <= mean <= 69:
average_grade = 'D'
else:
average_grade = 'F'
return mean, average_grade # have our function return both values, since it calculated them both anyways
compiled_scores = []
for test_score in input_scores:
letter_grade = determine_grade(test_score) # calling our single input/output function many times in a for loop
compiled_scores.append((test_score, letter_grade)) # creating a tuple so each letter and percent is stored together
mean_percent, mean_letter_grade = calc_average(input_scores) # decompile both values from our function
print("Score Numeric Grade Letter Grade")
print("--------------------------------------------")
# now we iterate through all the scores made and print them
for count, result_tuple in enumerate(compiled_scores, 1): # just print the scores in a loop
print("Score {}: ".format(count), result_tuple[0], " ", result_tuple[1])
print("--------------------------------------------")
print("Average Score: ", mean_percent, " ", mean_letter_grade)
You can see that we condensed our input() lines -> a single line, and condensed the print statements as well! Now our program can take, say, 30 scores and work just as well!!! (This is huge)!! And all that is required to change is the number 5 at the top of our script -> 30. No longer will we have to type print('this') or input('that')! Our script will automatically adjust because we made it able to scale with our list.
My test case (using same numbers from your post):
Enter score 1:90
Enter score 2:88
Enter score 3:76
Enter score 4:68
Enter score 5:40
Score Numeric Grade Letter Grade
--------------------------------------------
Score 1: 90.0 A
Score 2: 88.0 B
Score 3: 76.0 C
Score 4: 68.0 D
Score 5: 40.0 F
--------------------------------------------
Average Score: 72.4 C
Let me know if you need further clarification on something I posted!

Calculting GPA using While Loop (Python)

A GPA, or Grade point Average, is calculated by summing the grade points earned in a student’s courses and then dividing by the total units. The grade points for an individual course are calculated by multiplying the units for that course by the appropriate factor depending upon the grade received:
A receives 4 grade points
B receives 3 grade points
C receives 2 grade points
D receives 1 grade point
F receives 0 grade point
Your program will have a while loop to calculate multiple GPAs and a while loop to collect individual grades (i.e. a nested while loop).
For your demo, calculate the GPA to 2 decimal places for these two course combinations:
First Case: 5 units of A 4 units of B 3 units of C
Second Case: 6 units of A 6 units of B 4 units of C
This is what I have so far....
todo = int(input("How many GPA's would you like to calculate? "))
while True: x in range (1, todo+1)
n = int(input("How many courses will you input? "))
totpoints = 0
totunits = 0
while True: range(1, n+1)
grade = input("Enter grade for course: " )
if grade == 'A':
grade = int(4)
if grade == 'B':
grade = int(3)
if grade == 'C':
grade = int(2)
if grade == 'D':
grade = int(1)
if grade == 'F':
grade = int(0)
units = int(input("How many units was the course? "))
totunits += units
points = grade*units
totpoints += points
GPA = totpoints / totunits
print("GPA is ", ("%.2f" % GPA))
print("total points = ", totpoints)
print("total units = ", totunits)
My question is how do I exactly incorporate the while function correctly? My code is not running correctly.
Thanks in advance.
First thing you must know about Python is that is all about indentation. So make sure you indent your while blocks correctly. The syntax of the while statements is like:
while <condition>:
do_something
The code inside the while block is executed if the condition is true. After executing the code the condition is checked again. If the condition is still true it will execute the block again, and so on and so forth until the condition is false. Once the condition is false it exits the while block and keeps executing the code after.
One last thing, Python does not have case statements like other programming languages do. But you can use a dictionary, so for example I've defined a dictionary to map the grades to points and remove the if statements from your code:
gradeFactor = {'A':4, 'B': 3, 'C':2, 'D':1, 'F':0}
todo = int(raw_input("How many GPA's would you like to calculate? "))
while todo:
n = int(raw_input("How many courses will you input? "))
totpoints = 0
totunits = 0
while n:
grade = raw_input("Enter grade for course: " )
units = int(raw_input("How many units was the course? "))
totunits += units
points = gradeFactor[grade]*units
totpoints += points
n -= 1
GPA = float(totpoints) / totunits
print("GPA is ", ("%.2f" % GPA))
print("total points = ", totpoints)
print("total units = ", totunits)
todo -= 1

Python - Calculations Clashing. Need some sort of range variable

Im really stumped. Im writing a program for my teacher (Im using Python 3 btw), so that he can give this code to students to calculate their grade instead of waiting for their report card. I'm only a beginner so try and keep the answer simple please :D
Okay here is the problem. I have all of the inputs needed for the code. the inputs work like this. A = 5 B = 4 C = 3 D = 2 E = 1. If you got straight A's you'd get 50 points, and so on, but if it results in say, 35 points all the grade calculators will crash. Because if its >30 its a B, but if its >20 its a C, But >20 and >30 print at the same time. Because they both execute if the result is greater than 30. And i dont know how to make it so that it will print say, "B" if it is 31 to 40.
This is the code
a = eval(input())
b = eval(input())
c = eval(input())
d = eval(input())
e = eval(input())
f = eval(input())
g = eval(input())
h = eval(input())
i = eval(input())
j = eval(input())
average = a + b + c + d + e + f + g + h + i + j
print(average)
if average >41:
print(" Grade A ")
if average >31:
print(" Grade B")
if average >21:
print(" Grade C")
if average >11 :
print(" Grade D")
if average >0
print(" Grade E")
Any Help Would Be Greatly Appreciated! Thanks.
The best way to do what you want is to define a group of data. if/elif blocks work, but are ungainly, and require a lot of extra typing:
import sys
mark_boundaries = [("A", 41), ("B", 31), ("C", 21), ("D", 11), ("C", 0)]
try:
marks = []
for i in range(10):
marks.append(int(input()))
except ValueError:
print("You entered an invalid mark, it must be a number.")
sys.exit(1)
average = sum(marks) #I'd just like to note the misleading variable name here.
#average = sum(marks)/len(marks) #This would be the actual average mark.
print(average)
for mark, boundary in mark_boundaries:
if average >= boundary:
print("Grade "+mark)
break #We only want to print out the best grade they got.
Here we use a list of tuples to define our boundaries. We check from highest to lowest, breaking out if we match (so it doesn't 'fall through' to the lower scores).
Likewise, you can see that I have used a loop to gather the data in for the marks. A good sign that you are doing something in an inefficient way while programming is that you have copy and pasted (or typed out again and again) a bit of code. This generally means you need to put it in a loop, or make it a function. I also used int(input()) rather than eval(input()), which is a safer option, as it doesn't allow execution of anything the user wants. It also allows us to nicely catch the ValueError exception if the user types in something which isn't a number.
Note that an enterprising individual might look at a list of pair tuples and think a dict would be a good replacement. While true in most cases, in this case, we need to order to be right - in a dict the order is arbitrary, and might lead to us checking lower scores first, giving them a lower mark than they deserve.
Just as a note, it is entirely possible to do
if 31 < average < 41: #Equivalent to `if 31 < average and average < 41:`
print("Grade B")
In python. That said, for this usage, this would mean a lot more typing than using a list and loop or if/elif.
Basically, this is what you want:
if average >41:
print(" Grade A ")
elif average >31:
print(" Grade B")
elif average >21:
print(" Grade C")
elif average >11 :
print(" Grade D")
elif average >0
print(" Grade E")
else
print("You broke the system")
elif is short for else if, so it executes ONLY if the previous if/elif block was not executed.

Categories

Resources