S2Q2 · First Top Performer by Average¶
⚡ Quick Reference
Type: Full I/O problem
Core idea: accumulate scores per student, compute averages, find the highest with first-appearance tie-breaking.
n = int(input())
scores = {}
order = []
for _ in range(n):
name, score = input().split(",")
score = int(score)
if name not in scores:
scores[name] = []
order.append(name)
scores[name].append(score)
best = max(order, key=lambda name: sum(scores[name]) / len(scores[name]))
print(best)
Key rules:
- order list preserves first-appearance order
- scores dict maps name → list of scores
- max(order, key=lambda ...) - ties kept to first appearance since max only updates on strictly greater
Problem Statement¶
Problem (I/O type)
Read n name,score records. Compute average per student. Print the name of the student with the highest average. Ties → first to appear in input.
Example:
5
Alice,80
Bob,90
Alice,100
Bob,70
Carol,95
Carol
Averages: Alice = (80+100)/2 = 90.0, Bob = (90+70)/2 = 80.0, Carol = 95/1 = 95.0 → Carol wins.
Tracing the example¶
| Name | Scores | Average |
|---|---|---|
| Alice | [80, 100] | 90.0 |
| Bob | [90, 70] | 80.0 |
| Carol | [95] | 95.0 ← highest |
First-appearance order: Alice (line 1), Bob (line 2), Carol (line 5)
max(order, key=avg) → Carol (95.0) ✓
Solution approaches¶
from collections import defaultdict
n = int(input())
scores = defaultdict(list)
order = []
for _ in range(n):
name, score = input().split(",")
if name not in scores:
order.append(name)
scores[name].append(int(score))
print(max(order, key=lambda name: sum(scores[name]) / len(scores[name])))
defaultdict(list) auto-initialises empty lists. The if name not in scores check still works for tracking first appearance in order.
n = int(input())
scores = {}
order = []
for _ in range(n):
line = input()
name, score_str = line.split(",")
score = int(score_str)
if name not in scores:
scores[name] = []
order.append(name)
scores[name].append(score)
# Compute averages and find best
best_name = order[0]
best_avg = sum(scores[order[0]]) / len(scores[order[0]])
for name in order[1:]:
avg = sum(scores[name]) / len(scores[name])
if avg > best_avg:
best_avg = avg
best_name = name
print(best_name)
from collections import defaultdict
n = int(input())
scores = defaultdict(list)
order = []
lines = [input().split(",") for _ in range(n)]
for name, score in lines:
if name not in scores:
order.append(name)
scores[name].append(int(score))
avg = lambda name: sum(scores[name]) / len(scores[name])
print(max(order, key=avg))
Key takeaways¶
Separate order tracking from score accumulation
Use order list for first-appearance order and scores dict for the actual values. The list preserves insertion order; the dict provides O(1) lookup.
max(order, key=avg) preserves first on tie
max() iterates in the given order and only updates when it finds a strictly greater value. Iterating over order (first-appearance order) means ties keep the student who appeared first.
sum / len for running average
Store all scores in a list and compute sum/len at the end - simpler than maintaining a running average. For this problem size, the extra memory is negligible.