Python - Calculations Clashing. Need some sort of range variable - python

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.

Related

Python: Guessing a number is User's mind

I am stuck on a question from my Introduction to Python course. I have to write a code wherein the user keeps an integer in their mind, and the computer guesses. If the user's number is higher than the computer's guess, the user types "+", and the computer guesses higher. If the user's number is lower, the user types "-", and the computer guesses lower numer. If the computer guesses correctly, the user types "y", and the program ends.
Use the builtin function "input" to get a text from the user. If the user types anything other than "+", "-", or "y", the function should throw an exception.
Your function should take no arguments and return nothing.
I have to write the code in python.
The problem I am facing is that after checking for the input the first time, how to change the range and make the user enter their response again. I have just started coding, so please forgive me if it is a very basic question.
I was having the same problem you have and here is my solution for it:
import random
low = 1
high = 100
int(input("Enter the number for computer to guess: "))
while low != high:
guess = low + (high - low) // 2
high_low = input(f"Computer guess is: {guess} \n "
f"Press (H) for higher, (L) for lower and (C) for correct: ").casefold()
if high_low == "h":
low = guess + 1
elif high_low == "l":
high = guess - 1
elif high_low == "c":
print(f"I got it the number is {guess}")
break
else:
print("Please enter h, l or c")
else:
print(f"Your number is {low}")
Here I was using Binary Search algorithm with formula: guess = low + (high - low) // 2. To be more clear, what this formula does it starts of with guessing the mid point between high and low values. If we are told to guess higher that must mean our answer must be between 50 - 100. So the lowest it can be is 51 and that is our new lowest value for the range the mid point now becomes 51+(100-51)//2 (answer from this calculation is 75.5 integer division rounds down) so the result is 75. And If we are told now to guess lower that means answer must be somewhere between 51 and 75, so we know the answer is less than 75, the mid point now becomes 50+(75-51)//2
which is 62 and so on continues with that pattern. You can change H with +, L with -, and C with y and you will get your solution. I hope you find this useful :).
There are several solutions here, and some are more sophisticated than others.
The simplest solution in my opinion would simply be something like this (without validations):
if user_input == "+":
number = number + 1
elif user_input == "-":
number = number - 1
elif user_input = "y":
print("Number guessed correctly.")
Depending on the user input, the program will simply add or subtract 1 from the number. That way, you don't require range checks or anything the like.
Let me know if this approach is acceptable.

My code freezes and stops, what's wrong with it?

I'm new to python so don't be surprised it if is something really basic, but i've been trying to write this code that asks math questions and then saves the scores in order to show them again at the start of the loop, but it doesn't save the scores. what should i change?
this is the code
scores = []
names = []
while True:
f = open("highscore.txt", "r")
for line in f:
line = line.strip("\n")
line = line.split(" ")
names.append(line[0])
scores.append(int(line[1]))
print(f.read())
for pos in range(len(names)) :
print(pos + 1, names[pos], scores[pos])
f.close()
score = 0
print("hello, welcome to maths game")
print("\nQuestion 1: what is 2 x 2 x 2?")
answer = int(input("your answer >"))
if answer == 8:
print("correct")
score = score + 1
print("your score is ", score)
else:
print("incorrect")
print("the score is ", score)
print("\nQuestion 2: what is 34 x 2?")
answer = int(input("your answer >"))
if answer == 68:
print("correct")
score = score + 1
print("your score is", score)
else:
print("incorrect")
print("the score is", score)
name = input("what is your name?")
position = 0
for compare_score in scores :
if score < compare_score:
position = position + 1
scores.insert(position, score)
names.insert(position, name)
scores = scores[:5]
names = names[:5]
f = open("highscore.txt", "w")
for pos in range (len(names)):
f.write(names[pos] + " " + scores[pos])
it doesn't give any kind of error message, just loops back and doesn't save the names, neither the scores
You have a for-loop on scores that adds a new item to the scores list at each iteration. The for-loop will never reach the end of the list because there is always 'one more'.
Alain T.'s answer has already stated the root cause that you experienced. The loop never stops which appears to you as "freezing" since there are no outputs or indicators that you (as a user/developer) see that the loop still runs. So actually nothing freezes here .. it just runs forever.
For that reason I wanted to add a short note how to drill down the problem your own the next times..
Keyword here is clearly: debugging.
Debugging means: "finding out what your code does while being executed"
A very simple but (at least for small programs) quite effective approach is using one or more print() statements. These can be used to display the value of variables, the property of an object or just some statement like print("I am before the loop") to know where execution runs/stops..
A possible would be: (look at the print statements)
while True:
print("in while") #<-- this one
...
print("before loop") #<-- this one
for compare_score in scores :
print("in loop") #<-- this one repeats....
if score < compare_score:
position = position + 1
scores.insert(position, score)
names.insert(position, name)
scores = scores[:5]
names = names[:5]
print("After loop") #<-- never see this one
f = open("highscore.txt", "w")
for pos in range (len(names)):
f.write(names[pos] + " " + scores[pos])
Running your program again should print out:
in while
before loop
in loop
in loop
in loop
in loop
in loop
in loop
in loop
...
and so on... So what you know now is:
Everything before the loop at least executed
The loop runs forever .
So now it would be time to dig a little deeper inside the loop.
Most interesting would be to examine the variable on which the loop exit
depends.
In your case that is the length of the scores list:
for compare_score in scores:
So the loop runs until there are no more scores to compare left in the scores list.
So it might be a good idea to print() the length of the list to check if and how it decreases until there are no more scores to compare.
So add something like this:
Check the two print() statements containing len(scores)
for compare_score in scores:
print("in loop")
if score < compare_score:
position = position + 1
scores.insert(position, score)
names.insert(position, name)
scores = scores[:5]
names = names[:5]
print(len(scores)) #<--- this one
# or a bit nicer as f-string:
print(f"len score: {len(scores)}") #<--- this one
print("After loop")
Both are displaying the length of the scores list.
The former one just does it a little nicer.
There is a lot more to debugging. Many tools like VSCode, Pycharm, etc. support a lot more sophisticated methodologies to step through code, set breakpoints, inspect objects and variables ..
But for small ans simple projects and when the focus is on learning, instant feedback and repeating. At least to my mind. Print() debugging gives you a lot of insight in a very easy and simple manner.
Oh, and if you read until here:
"Welcome to the community" Just jokin', welcome !! ;)"

Grading Scale in Python Without Decision Statements

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()

Problems with my first python script [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I am trying to write a simple grading script based off an existing script that i found in a tutorial online. The goal is to ask the user their score and give the corresponding grade.
Here is the original code:
def letterGrade(score):
if score >= 90:
letter = 'A'
else: # grade must be B, C, D or F
if score >= 80:
letter = 'B'
else: # grade must be C, D or F
if score >= 70:
letter = 'C'
else: # grade must D or F
if score >= 60:
letter = 'D'
else:
letter = 'F'
return letter
this btw didnt work at all and i really dont get the "def" command since its not mentioned again? No errors
Anyway, here is my new modified code from what i have been learning from books and online...
score = float(input("What is your score"))
if score >= 90:
letter = 'A'
else: # grade must be B, C, D or F
if score >= 80:
letter = 'B'
else: # grade must be C, D or F
if score >= 70:
letter = 'C'
else: # grade must D or F
if score >= 60:
letter = 'D'
else:
letter = 'F'
print (letter)
input ("Press Enter to Exit")
This code doesnt work either, but at least it is asking for user input now. No errors
What am i missing here?
The def keyword introduces a function. In order for your script to work interactively, can you call the letterGrade function like this:
def letterGrade(score):
if score >= 90:
letter = 'A'
else: # grade must be B, C, D or F
if score >= 80:
letter = 'B'
else: # grade must be C, D or F
if score >= 70:
letter = 'C'
else: # grade must D or F
if score >= 60:
letter = 'D'
else:
letter = 'F'
return letter
if __name__ == '__main__':
score = float(input("What is your score? "))
print letterGrade(score)
input ("Press Enter to Exit")
Here, the __name__ == '__main__': block will be executed when you invoke your script from the command line (python your_script_name.py)
Ok let's first start with some pseudo code, I always try to pseudo code my problems and draw them out as much as possible, it helps me and it might help you. So the grading scale you seem to have implemented is something like this. If you have a grade lower than 100 but greater than or equal to 90 it is an A, lower than 90 but greater than or equal to an 80 it is a b, so on and so on. Let's use conditional statements for this. You can nest it like you had, but setting up the order of conditions may be what you need. So if the grade is not greater than or equal to 90, then the grade can only be lower than 90, thus a B, C, D or F.
if (grade >= 90):
letter = 'A'
elif (grade >= 80):
letter = 'B'
elif (grade >= 70)
letter = 'C'
elif (grade >= 60)
letter = 'D'
else:
letter = 'F'
So with these conditional statements we go through the process of finding the grade, as explained a bit above the code, if the user does not have a grade greater than 90, it hops to the next elif which checks if it is greater than or equal to 80, so on and so on, if grade at one point not greater than or equal to 60, then all other values lower than 60 will be an F.
Now to cover 'def'. You use def to define a function. Here is a generic layout:
def functioname(parameters, parameters):
stuffgoeshere
Now, the parameters are optional, it all depends if you need to pass any data to the function, in your case, you are passing the grade of the user:
def gradeLetter(grade):
if (grade >= 90):
return 'A'
elif (grade >= 80):
return 'B'
elif (grade >= 70)
return 'C'
elif (grade >= 60)
return 'D'
else:
return 'F'
At this point you can call the function, passing in the value the user typed in. We return the character in the function, so that you can assign it to a variable to print it, or you can just print it within the function, whichever is your preference.
g = input("Please enter your grade: ")
l = gradeLetter(g)
print("Your letter grade is " + l)
Hope this helps you out. If you have any questions feel free to comment below.
Since you are a noobie, let me give you a few tips.
1: SO is hostile to easily google-able things
If you google "python def" you'll see that it's the keyword for defining a function. What's a function? google. Oh, a function is a block of code that can be called multiple times.
def letterGrade(score):
if score >= 90:
letter = 'A'
else: # grade must be B, C, D or F
if score >= 80:
letter = 'B'
else: # grade must be C, D or F
if score >= 70:
letter = 'C'
else: # grade must D or F
if score >= 60:
letter = 'D'
else:
letter = 'F'
return letter
print(letterGrade(95)) # A
print(letterGrade(70)) # C
print(letterGrade(20)) # F
2: "else" and "if" can be combined in python:
def letterGrade(score):
if score >= 90:
letter = 'A'
elif score >= 80: # grade must be B, C, D or F
letter = 'B'
elif score >= 70: # grade must be C, D or F
letter = 'C'
elif score >= 60: # grade must D or F
letter = 'D'
else:
letter = 'F'
return letter
Omg hoooooooooooly crap! I need to apologize for wasting everyone's time. RPGillespie was correct, my code was working this entire time. Im new to using PyCharm and for some reason its set up in a way that you can be doing code at the top for one project, but actually "running" the code for a different project at the bottom. Iv been running the wrong code this entire time...day wasted!!! =(
I will say that i wont be making that mistake anymore. Geez, what a fiasco!!!
Thanks again for EVERYONE'S help and warm welcome. I will admit that as i am new to this forum, i am not new to forums in general. And its nice to not get eaten alive for asking a "noob" question or not knowing the un spoken rules of said forum. Its nice to find a place that actually tries to help its members.
My sincerest apologies again, i promise my next problem/question wont be wasting this forums time =).
iv undoubtedly earned the badge of "DOH" and "Facepalm".

How do you structure a recursive function?

I'm trying to create a recursive function that checks if a grade can be converted to a float, then checks to make sure the grade is between 0 and 100. My logic as to why this would work is:
Checks to see if the grade can be converted to a float.
If it can't be converted into a float, the user receives an error message, has to input a new grade, and gradeChecker checks again.
If it can be converted into a float, gradeChecker checks to see if it's between 0 and 100
If the grade between 0 and 100, the grade is then appended to the Assignments dictionary.
If the grade isn't between 0 and 100, the user gives a new grade, which is passed back in to the function, so repeat starting at step 1.
Can you tell me how this code doesn't follow that logic?
def gradeChecker(grade):
while True:
try:
grade = float(grade)
while (grade < 0) or (grade > 100):
print("Sorry, your grade must be between 0 and 100.")
grade = input("What grade did you receive on: %s? " % assignment)
gradeChecker(grade)
except:
print("Sorry, that's an invalid input. Please only use numbers and decimal points!")
grade = input("What grade did you receive on: %s? " % assignment)
else:
break
Assignments[assignment].append(grade)
Edit: Indentations fixed!
For reference, here is the entirety of the code I am using to pass grade into gradeChecker.
import collections #We import collections so we can use an ordered dictionary
Assignments = collections.OrderedDict() #We create an ordered dictionary called 'Assignments'
#We have to add each assignment to our dictionary individually because it's an ordered dictionary
#You can't convert a regular dictionary, which is unordered, to an ordered dictionary
#If you used a regular dictionary, when looping through the assignments they would be displayed at random
Assignments['Exam 1'] = [0.2] #We add the assignment and the weight to the dictionary
Assignments['Exam 2'] = [0.2] #We add the assignment and the weight to the dictionary
Assignments['Exam 3'] = [0.2] #We add the assignment and the weight to the dictionary
Assignments['Homework'] = [0.2] #We add the assignment and the weight to the dictionary
Assignments['LQR'] = [0.1] #We add the assignment and the weight to the dictionary
Assignments['Final'] = [0.1] #We add the assignment and the weight to the dictionary
#We have to define our grade checker before it is called so that it can be used to verify users inputs
def gradeChecker(grade): #Used to verify that a users grades are in-between 0 and 100
while True:
try:
grade = float(grade)
while (grade < 0) or (grade > 100):
print("Sorry, your grade must be between 0 and 100.")
grade = input("What grade did you receive on: %s? " % assignment)
gradeChecker(grade)
except:
print("Sorry, that's an invalid input. Please only use numbers and decimal points!")
grade = input("What grade did you receive on: %s? " % assignment)
else:
break
Assignments[assignment].append(grade) #We append the grade to the assignment to be used with it's weight for the final grade calculation
#INPUT
for assignment in Assignments.keys(): #We loop through every assignment in our Assignments dictionary
grade = input("What grade did you receive on: %s? " % assignment) #We ask the user to enter their grade
gradeChecker(grade) #We check to see if their grade is valid by passing their input through the gradeChecker function
Using both recursion and loop here is redundant. Moreover, loops should be preferred to recursion in 'normal' languages like Python (i.e., not Lisp) unless you're dealing with an inherently recursive data structure like a tree.
Given that you never stated why you need to use recursion in the first place, I suggest to use something like this:
def input_grade(assignment):
while True:
try:
grade = input("What grade did you receive on: %s? " % assignment)
grade = float(grade)
if grade < 0 or grade > 1000:
raise ValueError
return grade
except:
print("Sorry, that's an invalid input. Please only use numbers and decimal points!")
for assignment in Assignments:
Assignments[assignment].append(input_grade(assignment))
Note 1. I didn't test the code above, but it should give you the general idea of how to structure this function.
Note 2. You should avoid modifying Assignments in the function, that's an unwanted side effect. Better offload this to the main code.
Note 3. Technically, the try..except in my code is an example of exception-based logic, which isn't a great thing (however, this is way better than using recursion here).
def gradeChecker(grade):
try:
grade = float(grade)
while (grade < 0) or (grade > 100):
print("Sorry, your grade must be between 0 and 100.")
grade = input("What grade did you receive on: %s? " % assignment)
gradeChecker(grade)
except:
print("Sorry, that's an invalid input. Please only use numbers and decimal points!")
grade = input("What grade did you receive on: %s? " % assignment)
else:
Assignments[assignment].append(grade)
the thing with your code is that it's redundant; the while statement is there to do what you already have the recursive calls doing. imo, the while statement is better since recursion often uses up more memory but thats just an opinion.

Categories

Resources