{ }codelper
comprehensionsgroupingP0206

Build an answer-sheet score table

You are given the answer key string K of a test.
The questions are numbered 1 to L (L is the length of K), and the i-th character of K is the answer to question i. You are given the answer sheets of n students.
A sheet is a string of A to E and .
(skipped), with length at least 1 and at most L. If a sheet is shorter than L, the missing questions at the end count as skipped. A correct answer scores 3 points, a wrong one -1 point, and a skipped one 0 points. Instead of loops, build and print the following with list comprehensions, generator expressions and built-in tools such as the zip family, enumerate, sorted and itertools.groupby. 1) For each student in input order, print one line "name score correct wrong skipped". 2) Group students with the same score, and print one line "score name1 name2 ..." per group, from the highest score.
Within a group, write the names in input order. 3) Print, on one line separated by spaces from the smallest, the numbers of the questions that the most students got wrong.
If nobody got any question wrong, print -.

Input
First line K (uppercase A to E, 1 ≤ L ≤ 100).
Second line n (1 ≤ n ≤ 1000).
Then n lines "name sheet".
Names are 1 to 10 lowercase letters and digits, all different.
Output
1) n lines, 2) one line per different score, 3) one line
Example 1 · stdin
ABCDE
4
mina ABCDD
joon AB
sora .BCEA
ted EBC
stdout
mina 11 4 1 0
joon 6 2 0 3
sora 4 2 2 1
ted 5 2 1 2
11 mina
6 joon
5 ted
4 sora
5
Example 2 · stdin
CAB
3
amy CAB
bo C.B
cy CAB
stdout
amy 9 3 0 0
bo 6 2 0 1
cy 9 3 0 0
9 amy cy
6 bo
-
main.py
Input (stdin)

When you run, these lines are fed to input()/stdin in order (the program doesn't stop to ask).

$ Ready

Open this on a computer to write and run code. On mobile you can read the problem and the solutions.

In other languagesShow solutions by language · 1 languages

This problem takes only Python, because list comprehensions and generator expressions are Python syntax.
Other languages do the same with loops, or map/filter (JS), stream groupingBy (Java), LINQ Zip/GroupBy (C#).
In Craykon you would count with for and Dict().
In the comprehension that turns each question into one of O, X or .
— ["." if a == "." else "O" if a == k else "X" for a, k in ...] — the leading x if cond else y chooses a value, while a trailing if filters, so they go in different places.
Five traps: (1) zip(sheet, key) stops at the shorter one, so the missing questions of a short sheet vanish (the skipped count drops).
Pair up to the end with itertools.zip_longest(sheet, key, fillvalue=".") (since 3.10, zip(..., strict=True) raises an error when the lengths must match).
(2) itertools.groupby groups only adjacent equal values.
Without sorting by score first, one score splits into several groups.
sorted is stable, so even in descending order with reverse=True students with the same score keep their input order.
(3) enumerate counts from 0.
Count question numbers from 1 with enumerate(..., start=1).
(4) Writing the conditional as just "O if correct, else X" makes a skipped . wrong too.
(5) If nobody got anything wrong, the highest wrong count is 0, and picking by it selects every question.
When it is 0 keep an empty list, and print - for an empty string with " ".join(...) or "-".
True adds as 1, so a generator expression like sum(m[i] == "X" for ...) counts directly.

Pythonmain.py · 30 lines
from itertools import groupby, zip_longest key = input().strip()n = int(input())rows = [input().split() for _ in range(n)] # 문항마다 O(맞음)·X(틀림)·.(건너뜀). 짧은 답안은 zip_longest가 "."로 채워 끝까지 짝짓는다sheets = [    (name, ["." if a == "." else "O" if a == k else "X" for a, k in zip_longest(ans, key, fillvalue=".")])    for name, ans in rows] # 1) 학생마다: 이름 점수 맞은수 틀린수 건너뛴수stats = [(name, 3 * m.count("O") - m.count("X"), m.count("O"), m.count("X"), m.count(".")) for name, m in sheets]print("\n".join(" ".join(map(str, s)) for s in stats))  def score(s):    return s[1]  # 2) 같은 점수끼리: groupby는 붙어 있는 것만 묶으므로 먼저 점수로 정렬한다(정렬은 안정적이라 입력 순서가 남는다)ranked = sorted(stats, key=score, reverse=True)print("\n".join(f"{pts} " + " ".join(s[0] for s in grp) for pts, grp in groupby(ranked, key=score))) # 3) 가장 많이 틀린 문항(번호는 1부터)wrong = [sum(m[i] == "X" for _, m in sheets) for i in range(len(key))]top = max(wrong)worst = [q for q, w in enumerate(wrong, start=1) if w == top] if top > 0 else []print(" ".join(map(str, worst)) or "-")