Build a program that reads student scores from a file and produces a report.
The input file has one student per line, name and score separated by a comma:
Ada,92
Grace,85
Alan,58
Define four functions.
read_scores(path) — reads the file and returns a dictionary mapping each name to their score as an int. Skip blank lines.grade_letter(score) — returns "A" for 90 and above, "B" for 80–89, "C" for 70–79, "D" for 60–69, "F" below 60. This is the function from the conditionals section — write it again from memory.class_average(scores) — takes the dictionary and returns the average score. Assume at least one student.report_lines(scores) — returns a list of strings, one per student, sorted by name, each in the form:<name>: <score> (<letter>)
For the file above, report_lines(read_scores(path)) returns:
['Ada: 92 (A)', 'Alan: 58 (F)', 'Grace: 85 (B)']
and class_average returns 78.33....
Run your code to see the output, then press Submit.
read_scores, split each line on ",", strip the pieces, and convert the score with int.class_average sums scores.values() and divides by len(scores).report_lines calls grade_letter for each student — build it after the others work.import unittest
class TestGradeReport(unittest.TestCase):
def setUp(self):
with open("test_scores.txt", "w") as file:
file.write("Ada,92\nGrace,85\n\nAlan,58\n")
def test_read_scores_parses_names_and_ints(self):
self.assertEqual(
read_scores("test_scores.txt"),
{"Ada": 92, "Grace": 85, "Alan": 58},
)
def test_grade_letter_boundaries(self):
self.assertEqual(grade_letter(90), "A")
self.assertEqual(grade_letter(89), "B")
self.assertEqual(grade_letter(70), "C")
self.assertEqual(grade_letter(65), "D")
self.assertEqual(grade_letter(59), "F")
def test_class_average(self):
self.assertAlmostEqual(class_average({"Ada": 92, "Grace": 85, "Alan": 58}), 78.33333333333333)
def test_report_lines_sorted_and_formatted(self):
scores = read_scores("test_scores.txt")
self.assertEqual(
report_lines(scores),
["Ada: 92 (A)", "Alan: 58 (F)", "Grace: 85 (B)"],
)
def test_single_student_average(self):
self.assertAlmostEqual(class_average({"Ada": 80}), 80.0)
def read_scores(path):
scores = {}
with open(path) as file:
for line in file:
if line.strip() == "":
continue
name, score = line.strip().split(",")
scores[name.strip()] = int(score.strip())
return scores
def grade_letter(score):
if score >= 90:
return "A"
elif score >= 80:
return "B"
elif score >= 70:
return "C"
elif score >= 60:
return "D"
else:
return "F"
def class_average(scores):
return sum(scores.values()) / len(scores)
def report_lines(scores):
lines = []
for name in sorted(scores):
score = scores[name]
lines.append(f"{name}: {score} ({grade_letter(score)})")
return lines
with open("scores.txt", "w") as file:
file.write("Ada,92\nGrace,85\nAlan,58\n")
scores = read_scores("scores.txt")
for line in report_lines(scores):
print(line)
print(class_average(scores))
Sign in to join the discussion.
No comments yet. Be the first to ask a question.
Press Run to execute your code, or Submit to test and complete this problem.