Each row is name,subject,marks. For every subject, in alphabetical order, print:
- the topper: the highest mark; if two students tie, the alphabetically smaller name;
- the topper's mark;
- the average mark for the subject, with exactly 2 decimal places.
Constraints
- 1 ≤ n ≤ 10^4
Input and output
- Input
- First line: n. Then n lines `name,subject,marks` (marks are integers from 0 to 100; no spaces).
- Output
- One line per subject: `subject topper marks average`.
Examples
Input 1
6
Riya,maths,91
Dev,maths,91
Arjun,physics,78
Riya,physics,64
Dev,dsa,88
Tara,maths,70Output
dsa Dev 88 88.00
maths Dev 91 84.00
physics Arjun 78 71.00Dev and Riya tie on 91 in maths; Dev comes first alphabetically. The maths average is (91 + 91 + 70) / 3 = 84.00.
Input 2
2
Sana,os,0
Neha,os,1Output
os Neha 1 0.50A 0 is a valid mark. The average is 0.50.
Show hints
- Keep one running record per subject: the best (marks, name), the total and the count.
- To compare "highest mark, then smallest name" with one
max, use the key(marks, reversed name order). Or compare tuples by hand.
Show the explanation
Make one pass and keep a small record per subject:
best = {} # subject -> (marks, name)
total, count = defaultdict(int), defaultdict(int)
for row in rows:
name, subject, m = row.split(",")
m = int(m)
total[subject] += m
count[subject] += 1
cur = best.get(subject)
if cur is None or m > cur[0] or (m == cur[0] and name < cur[1]):
best[subject] = (m, name)Then for each subject in sorted(best), print the topper and f"{total[subject] / count[subject]:.2f}".
Discussion points
- One pass, O(n) memory per subject at most. The rows do not need to be stored, so the same code works on a file streamed line by line:
for line in open(path). - Tie-breaking. The rule "highest marks, then smallest name" mixes descending and ascending order. Write the comparison explicitly, or sort with
key=lambda r: (-r.marks, r.name)and take the first row. - Real CSV files can contain quoted commas. Then use the
csvmodule (csv.reader) rather thansplit(","). In data work,pandas.read_csvwithgroupby("subject").agg(...)does this in two lines. Interviewers often ask for both versions. - Formatting:
:.2frounds the floating-point value. Values exactly halfway between two outputs can depend on binary representation. For money, usedecimal.Decimal.
Original UniCircle question. Last reviewed 22 Oct 2026.
