beginner programmer here..easier ways to program this? - python

I am a beginner programmer and am self learning python programming at home from a book. I am currently learning about strings. There is a question there which i solved it but I was thinking if there are other easier ways to solve it.
Q. A certain professor gives 100-point exams that are graded on the scale 90-100:A, 80-89:B, 70-79:C, 60-69:D, <60:F. Write a program that accepts an exam score as input and prints out the corresponding grade.
def main():
## making a list from 0-100
num = list(range(0,101))
## asking for the exam points
points = int(input("Enter the exam points 0-100: "))
## iterating num 0-60
for i in num[0:60]:
if i == points:
print("Your corresponding grade is F.")
## iterating num 60-70
for i in num[60:70]:
if i == points:
print("Your corresponding grade is D.")
## iterating num 70-80
for i in num[70:80]:
if i == points:
print("Your corresponding grade is C.")
## iterating num 80-90
for i in num[80:90]:
if i == points:
print("Your corresponding grade is B.")
## iterating num 90-100
for i in num[90:101]:
if i == points:
print("Your corresponding grade is A.")
main()

Yes, there is a much better way of writing that.
Given that you have an int, which is the score, all you have to do is compare it to the boundaries that determine the grade (using < or >).
points = int(input("Enter the exam points 0-100: "))
if points < 60:
grade = 'F'
elif points < 70:
grade = 'D'
elif points < 80:
grade = 'C'
elif points < 90:
grade = 'B'
else:
grade = 'A'
print("Your corresponding grade is", grade)
To make your code clearer, you can put the comparison logic into a function that returns the grade for a given score.
def calculate_grade(score):
if score < 60:
return 'F'
if score < 70:
return 'D'
if score < 80:
return 'C'
if score < 90:
return 'B'
return 'A'
def main():
points = int(input("Enter the exam points 0-100: "))
grade = calculate_grade(points)
print("Your corresponding grade is", grade)

There's still an easier and more concise way to do this. Try this:
points = int(input("Enter the exam points 0-100: "))
if 0 < points <= 60:
print "Your grade is F"
elif 60 < points <= 70:
print "Your grade is E"
elif 70 < points <= 80:
print "Your grade is D"
[and so on...]
Benefits are:
Plain comparisons instead of heavy linear search
No need to define any kind of dictionaries, methods or even classes or the like (especially since you mentioned you're not that experienced in Python by now)
Exits when it has found the right grade and doesn't evaluate further needless ifs

It is correct (gives the expected grade) and terribly inefficient:
you create an array when it could be avoided
you use linear search in arrays where simple comparisons would be enough
In addition you use a pure linear (unstructured) design.
You could:
make a function that converts points to grade
call it from a main that deals with input and output
Code example
def points_to_grade(points):
limits = [90, 80, 70, 60]
grades = ['A', 'B', 'C', 'D']
for i,limit in enumerate(limits):
if points >= limit:
return grade[i]
return 'F'
def main():
## asking for the exam points
points = int(input("Enter the exam points 0-100: "))
## convert to grade
grade = points_to_grade(points)
print("Your corresponding grade is {}.".format(grade))

#Maybe using dictionaries is more fun :)
marks = {'F':60, 'D':70,'C':80,'B':90}
points = int(input("Enter the exam points 0-100: "))
for key,value in marks.items():
if points<=value:
print("Your corresponding grade is ", key)
break
print("Your corresponding grade is A")

I do not code in python so I might not use right syntax but this is pretty much same in all languages. Iterating trough all values is bad practice. You just need few if statements (or switch/case), something like this:
if i<=100 and i>=90:
print("Grade is A")
if i<=89 and i>=80:
print("Grade is B")
etc....

def main():
points = int(input('Enter the exam points:'))
if points >= 90:
print('Your corresponding grade is A')
elif 80 <= points <= 90:
print('Your corresponding grade is B.')
elif 70 <= points <= 80:
print('Your corresponding grade is C.')
elif 60 <= points <= 70:
print('Your corresponding grade is D.')
elif 0 <= points <= 60:
print('Your corresponding grade is F.')

your solution is pretty not optimal and could be solved really nice using some basic logic, like below, which will perform better and would be more readable:
## asking for the exam points
point = int(input("Enter the exam points 0-100: "))
point_set = 'FEDCBA'
if point == 100:
print('A')
else:
print(point_set[point // 10 - 5])
code is using simple logic, once point is less than 60, 59 // 10 evaluates to 5 and 5 - 5 = 0, so grade at index 0 will be used - F. In case point is 100, this is some edge case, and that's why I'm using special if, for other cases there is simple math, which is self explanatory.

Yes there is, I would have used this approach
def main():
points = int(input("Enter the exam points 0-100: "))
if points >= 60:
print("Your corresponding grade is F.")
elif points > 60 and points < 70:
print("Your corresponding grade is D.")
elif points > 70 and points < 80:
print("Your corresponding grade is C.")
elif points > 80 and points < 90:
print("Your corresponding grade is B.")
elif points > 90:
print("Your corresponding grade is A.")
else:
print("Error: invalid value")

Related

Stuck on this Python program

Image to problem
The for loop works, though I can't figure out how to put the grade on a single line as shown in the photo. It asks for grades individualy when ran instead.
Here is my code:
num_students = int(input("Enter the number of students: "))
scores = []
for i in range(num_students):
scores.append(int(input("Enter a score: ")))
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)
Use a single input() call instead of a loop, and use .split() to get each individual score.
num_students = int(input("Enter the number of students: "))
scores = input(f"Enter {num_students} scores: ")
scores = [int(score) for score in scores.split()]
As John Gordon answered, your main issue is calling input inside a loop. That dictates that each user response will be on its own line. To fix this, call input once, then break the resulting string up using .split(). Split when called with no arguments will break a string into a list at each space.
Here is an example of how to do this (without the f strings and list comprehensions from John's answer):
num_students = int(input("Enter the number of students: "))
score_string = input("Enter " + str(num_students) + " scores: ")
scores = []
for score in score_string.split():
scores.append(int(score))

I get a syntaxt error when I try to run the program

I get a syntax error on the last else statement. This is supposed to be a grade calculator. If someone enters anything that isn't between 0 and 100, then the program should send a message, and then loop until a valid number is entered. Also I am new to programming, so if there is something else wrong with my code, please let me know!
number = int(input("Enter the numeric grade: "))
if number > 89:
letter = 'A'
elif number > 79:
letter = 'B'
elif number > 69:
letter = 'C'
else:
letter = 'F'
print("The letter grade is", letter)
number = int(input("Enter the numeric grade: "))
if number > 100:
print("Error: grade must be between 100 and O")
elif number < 0:
print("Error: grade must be between 100 and O")
else:
# The code to compute and print the result goes here
number = int(input("Enter the numeric grade: "))
if number > 100 or number < 0:
print("Error: grade must be between 100 and 0")
else:
# The code to compute and print the result goes here
number = int(input("Enter the numeric grade: "))
if number >= 0 and number <= 100:
else:
print("Error: grade must be between 100 and O")
Your issue is at the bottom, where you've got an empty if statement followed by an else statement, as well as incorrect indenting. From your code, I believe you are trying to use not.
I would suggest doing one of two things:
1.
if not (number >= 0 and number <= 100):
2.
if number < 0 or number > 100:
These two pieces of code will both produce the same result.
Also, it seems as though you are repeating the same code several times to try to ensure that the user inputs a number between 0 and 100. If so, this can be achieved with a while loop. I've put an example of this below:
number = int(input("Enter the numeric grade: "))
while number < 0 or number > 100:
print("Error: grade must be between 100 and O")
number = int(input("Enter the numeric grade: "))
In the last line.
if number >= 0 and number <= 100:
else:
print("Error: grade must be between 100 and O")
you didn't write anything after the if statement.
This code will run
if number >= 0 and number <= 100:
print('Write something here')
else:
print("Error: grade must be between 100 and O")
or you can just remove the last if statement its really of no use like try doing something else because there are a lot of if and else statements which don't look nice.
try this:
n = int(input())
first = 0
last = 100
while n < first or n > last:
print(n,'is not a valid input')
n = int(input())
From what I've understood, you're trying loop indefinitely until the user input is between 0 and 100.
My solution would be this:
Define a function that starts by requesting an input from the user.
Use a while loop that will check if the input is 'correct'. In case the input is not correct, the loop will print the error and call back the function again indefinitely till the user's input is between 0 and 100.
if the input is between that range, it will then evaluate the grade and return it.
def yfunc():
n = int(input('Enter the numeric grade: '))
while n < 0 or n > 100:
print("Error: grade must be between 100 and O")
return yfunc()
if n > 89:
letter = 'A'
elif n > 79:
letter = 'B'
elif n > 69:
letter = 'C'
else:
letter = 'F'
return letter
yfunc()
If you have any questions, feel free to ask.

What to do when main() function isn’t calling/executing the other functions?

I created a main() function and also 3 others and I am trying to get the other 3 to be executed into main()
I had it working then I messed it up at the very end, so I commented it out since it is not calling the 3 other functions.
# The program displays the letter grade and associated message for each exam score
# and the average exam score
# The program will not contain any repeated code and have a minimum of two functions besides Main.
def main():
# ask user to enter test scores
score = int(input("Enter your test scores separate by spaces, no commas: "))
# display test score
def showLetters(num, letterGrade):
print(f"{num:.1f} is an {letterGrade}\n")
# display score message
def examScores(num):
if 90 <= num <= 100:
letterGrade = "A"
print("Excellent Work")
elif 80 <= num <= 89:
letterGrade = "B"
print("Nice job")
elif 70 <= num <= 79:
letterGrade = "C"
print("Not bad")
elif 60 <= num <= 69:
letterGrade = "D"
print("Room for improvement")
else:
letterGrade = "F"
print("Go back and review")
return letterGrade
# calculate average of all scores entered by user
def calcAverages(grades):
numbers = scores.split()
for i in range(len(numbers)):
numbers[i] = int(numbers[i])
print("Average exam score: ", sum(numbers) / len(numbers))
# ask user to repeat or quit
answer = str(input('Please enter "y" to run program again or "n" to exit: '))
if answer.lower() == 'n':
print('Thank you for using! Goodbye!')
sys.exit()
elif answer.lower() == 'y':
main()
# ??? = main()
# for n in ????? :
# showLetters(n, examScores(n, calcAverages(????)))
I made minor edits to your program and you now have the average values.
I have highlighted only the lines that need addition.
counter = 0 # tracks the number of times the function is called
#added the below 2 lines after counter
sumCredit = 0 #tracks the sum credit for all the students
sumStudyHrs = 0 #track the sum of the study hours for all the students
def myfunction():
global counter # tracks the number of times the function is called
#added two more global variables to keep track of the averages
global sumCredit #track the sum credit
global sumStudyHrs #track the sum study hours
the rest of the code can stay as is. Immediately after you print the student details, you need to accumulate the values so you can calculate the average.
print("Study hours: " + str(sumHours))
#added the below 2 lines after your print statements
sumCredit += classes
sumStudyHrs += sumHours
# Ask user if they want to end or restart
Now you need to use this information for your calculation.
When you print the average, use the above variables to compute the average.
print("Total Students: " + str(counter)) # tracks the number of times the function is called
#modified your average credits and average study with correct numerator
print("Average Credits: " + str(sumCredit / counter)) #computer average credits
print("Average Study Hours: " + str(sumStudyHrs / counter)) #compute average study hours
print('Thank you for using! Goodbye!')
This should give you the desired results.
Let me know if you need the full code.

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!

How can I rank a input list and assign it a variable to return to user?

I'm having a hard time with my program and my code skills are quite elementary. What I need to do is take an inputted list from the user and rank them by letter A (66 - 100), B (33 - 65), C (0 - 32). I assume I need the inputted list to be a tuple but I'm not entirely sure how to do so. I know I need to (or can) use an elif to accomplish this but I'm not sure how to make it a range between two numbers for B since C is else, and A is just greater than.
This is my code:
def scores():
print('we are starting')
count = int(input('Enter amount of scores: '))
print('Each will be entered one per line')
scoreList = []
for i in range(1, count+1):
scoreList.append(int(input('Enter score: ')))
print(scoreList)
print(scoreList)
if scoreList > 66:
print('A')
#elif scoreList > 33:
#print('B')
else:
print ('C')
Just chain together your conditions using logical operators (and, or, not) and loop through each item in the list:
def scores():
print('we are starting')
count = int(input('Enter amount of scores: '))
print('Each will be entered one per line')
scoreList = []
for i in range(1, count+1):
scoreList.append(int(input('Enter score: ')))
print(scoreList)
print(scoreList)
for score in scoreList:
if score >= 66:
print('A')
elif score >= 35 and score <=65:
print('B')
else:
print('C')
A possible solution for the if-structure:
for score in scoreList:
if 66 <= score <= 100:
print('A')
elif 33 <= score <= 65:
print('B')
elif 0 <= score <= 32:
print('C')
else:
# handle out of range input
This way you can use the else to handle input that isn't between 0 and 100.

Categories

Resources