Python if elif and loops - python

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]}")

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

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)

Python: Returning array values from a function

I'm trying to understand how to use functions properly. In this code, I want to return 2 arrays for pupil names and percentage scores. However I am unable to return the array variables from the first function.
I've tried using different ways of defining the arrays (with and without brackets, both globally and locally)
This is the relevant section of code for the program
#function to ask user to input name and score
def GetInput():
for counter in range(0,10):
names[counter] = input("Please enter the student's name: ")
valid = False
while valid == False:
percentages[counter] = int(input("Please enter the student's score %: "))
if percentages[counter] < 0 or percentages[counter] > 100:
print("Please enter a valid % [0-100]")
else:
valid = True
return names, percentages
name, mark = GetInput()
I'm expecting to be asked to enter the values for both arrays.
I'm instead getting:
Traceback (most recent call last):
File "H:/py/H/marks.py", line 35, in <module>
name, mark = GetInput()
File "H:/py/H/marks.py", line 7, in GetInput
names[counter] = input("Please enter the student's name: ")
NameError: global name 'names' is not defined
You need to use dictionary instead of list if your want to use key-value pairs. furthermore you need to return the values outside of for loop. You can try the following code.
Code:
def GetInput():
names = {} # Needs to declare your dict
percentages = {} # Needs to declare your dict
for counter in range(0, 3):
names[counter] = input("Please enter the student's name: ")
valid = False
while valid == False:
percentages[counter] = int(input("Please enter the student's score %: "))
if percentages[counter] < 0 or percentages[counter] > 100:
print("Please enter a valid % [0-100]")
else:
valid = True
return names, percentages # Return outside of for loop.
name, mark = GetInput()
print(name)
print(mark)
Output:
>>> python3 test.py
Please enter the student's name: bob
Please enter the student's score %: 20
Please enter the student's name: ann
Please enter the student's score %: 30
Please enter the student's name: joe
Please enter the student's score %: 40
{0: 'bob', 1: 'ann', 2: 'joe'}
{0: 20, 1: 30, 2: 40}
If you want to create a common dictionary which contains the students' name and percentages, you can try the following implementation:
Code:
def GetInput():
students = {}
for _ in range(0, 3):
student_name = input("Please enter the student's name: ")
valid = False
while not valid:
student_percentages = int(input("Please enter the student's score %: "))
if student_percentages < 0 or student_percentages > 100:
print("Please enter a valid % [0-100]")
continue
valid = True
students[student_name] = student_percentages
return students
students = GetInput()
print(students)
Output:
>>> python3 test.py
Please enter the student's name: ann
Please enter the student's score %: 20
Please enter the student's name: bob
Please enter the student's score %: 30
Please enter the student's name: joe
Please enter the student's score %: 40
{'ann': 20, 'bob': 30, 'joe': 40}
You forgot to set the names and percentages as empty dictionaries so you can use them. Also the "return" should be outside of the for loop.:
def GetInput():
names={}
percentages={}
for counter in range(0,10):
names[counter] = input("Please enter the student's name: ")
valid = False
while valid == False:
percentages[counter] = int(input("Please enter the student's score %: "))
if percentages[counter] < 0 or percentages[counter] > 100:
print("Please enter a valid % [0-100]")
else:
valid = True
return names, percentages
name, mark = GetInput()
Probably this may help to you.
#function to ask user to input name and score
def GetInput():
names=[]
percentages=[]
for counter in range(0,3):
names.append(input("Please enter the student's name: "))
valid = False
while valid == False:
percentages.append(int(input("Please enter the student's score %: ")))
if percentages[counter] < 0 or percentages[counter] > 100:
print("Please enter a valid % [0-100]")
else:
valid = True
return names, percentages
name, mark = GetInput()
print(name,mark)
This is implemented by using two lists. (Not suggested for keeping records. Better use dictionary as done below.)
counter = 10
def GetInput():
names = []
percentage = []
for i in range(counter):
names.append(input("Please enter the student's name: "))
valid = False
while not(valid):
try:
percent = int(input("Please enter the student's score between 0 and 100%: "))
if percent >= 0 and percent <= 100:
percentage.append(percent)
valid = True
break
else:
continue
except ValueError:
print("\nEnter valid marks!!!")
continue
valid = True
return names, percentage
students, marks = GetInput()
The following is implemented by using dictionary, and for this, you do not need the variable counter.
def GetInput():
records = dict()
for i in range(counter):
name = input("Please enter the student's name: ")
valid = False
while not(valid):
try:
percent = int(input("Please enter the student's score between 0 and 100%: "))
if percent >= 0 and percent <= 100:
#percentage.append(percent)
valid = True
break
else:
continue
except ValueError:
print("\nEnter valid marks!!!")
continue
valid = True
records[name] = percent
return records
record = GetInput()
Change the value of counter to how many records you want. This takes care of marks to be between 0 and 100 (included) and to be integer. Its better if you implement it with dictionary.
Wouldn't it be better to have name and percentage in one dict?
#function to ask user to input name and score
def GetInput():
name_percentage = {}
for counter in range(0,10):
name = input("Please enter the student's name: ")
valid = False
while not valid:
percentage = int(input("Please enter the student's score %: "))
if percentage < 0 or percentage > 100:
print("Please enter a valid % [0-100]")
else:
valid = True
name_percentage[name] = percentage
return name_percentage
name_percentage = GetInput()
print(name_percentage)

Trying to call read/write functions

I am a beginner programmer learning python in my intro game development class. The current homework assignment is to create a function to read and write files. We have to do it also where we can use user input to find the file directory. The problem I'n currently having is that I can't figure out how to write the function to open and close the files. I'll post my code for any help. Thank you. I am only focused on Option 8 for the time being.
enter = 0
start = 0
Roger = ()
text_file = ()
line = open("read.txt", "r")
def read_file(line):
for line in text_file:
print(line)
return line
def close_file(text_file):
text_file.close()
return close_file
def update_score(scores, person, amount):
for score in scores:
if score[0].lower() == person.lower():
score[1] += amount
return scores
def update_score1(scores, person, amount):
for score in scores:
if score[0].lower() == person.lower():
score[1] -= amount
return scores
def addition(num1):
return num1 + num1
def square(num):
print("I'm in square")
return num * num
def display(message):
"""Display game instuctions"""
print(message)
def instructions():
"""Display game instuctions"""
print("Welcome to the world's greatest game")
def main():
str1 = ["Roger", 3456]
str2 = ["Justin", 2320]
str3 = ["Beth", 1422]
instructions()
scores = [str1, str2, str3]
start = input("Would you like to view the high score options? y/n ")
if start == "y":
print("""\
Hello! Welcome to the high scores!
Here are the current high score leaders!:
""")
print(scores)
print("""\n\
0 - Sort high scores
1 - Add high score
2 - Reverse the order
3 - Remove a score
4 - Square a number
5 - Add 2 numbers together
6 - Add to a score
7 - Subtract from a score
8 - Read a file
9 - Write to a file
""")
option = int(input("Please enter your selection "))
while option < 8:
print(scores)
if option == 0:
scores.sort()
print("These are the scores sorted alphabetically")
print(scores)
option = option = int(input("Please enter your selection"))
elif option == 1:
print(scores)
print("Please enter your name and score; After entering your name, hit the return key and enter your score")
name = input()
score = int(input())
entry = (name,score)
scores.append(entry)
print(scores)
option = option = int(input("Please enter your selection"))
elif option == 2:
print(scores)
scores.reverse()
print("\nHere are the scores reversed")
print(scores)
option = option = int(input("Please enter your selection"))
elif option == 3:
print(scores)
print("Please enter the high score you would like to remove. After typing the name, hit the return key and enter the score")
name1 = input()
score1 = int(input())
remove = (name1,score1)
scores.remove(remove)
print(scores)
option = option = int(input("Please enter your selection"))
elif option == 4:
val = int(input("Give me a number to square"))
sqd = square(val)
print(sqd)
option = option = int(input("Please enter your selection"))
elif option == 5:
val0 = int(input("Give me one number"))
val1 = int(input("Give me another number"))
addi = (val0 + val1)
print(addi)
option = option = int(input("Please enter your selection"))
elif option == 6:
print(scores)
sc0 = input("Please enter player whose score you would like to increase. ")
sc1 = int(input("Please enter the amount would would like to add to their score. "))
scores = update_score(scores, sc0, sc1)
print(scores)
option = option = int(input("Please enter your selection"))
elif option == 7:
sc2 = input("Please enter player whose score you would like to decrease. ")
sc3 = int(input("Please enter the amount you would like to subtract from their score. "))
scores = update_score1(scores, sc2, sc3)
print(scores)
while option <= 8:
if option == 8:
print (line)
text_file.close()
option = option = int(input("Please enter your selection"))
main()
Function to return a file's contents:
def read_file(filename):
return open(filename).read()
To write to a file:
def write_file(filename, toWrite):
file = open(filename, 'w')
file.write(toWrite)
file.close()
Example usage:
stuffInFile = read_file("myfile.txt")
write_file("myfile.txt", "I just wrote this to a file!")

Finding A Collective Average & Letter Grade For Tests & Assignments

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)

Categories

Resources