{ }codelper
レコードレコードのリスト条件つき並べ替えP0067

成績順位表

一行目に学生の数 n が与えられ、続く n 行に "名前 国語 英語 数学" が空白一つずつで区切られて与えられる。
学生ごとに三科目の合計を求めて順位表を出力せよ。
合計が大きい学生から書き、合計が同じなら名前の文字コード順(ASCII:大文字が小文字より先、先頭が同じなら短いほうが先)で書く。
各行に "順位 名前 合計" を出力する。
順位は 1 +(自分より合計が大きい学生の数)である。
したがって合計が同じ学生は順位が同じで、次の順位はその分飛ぶ(例:1, 1, 3)。

入力
1 ≤ n ≤ 1000、0 ≤ 点数 ≤ 100(整数)。
名前は英大文字・小文字 1〜10 文字で互いに異なる
出力
n 行、各行に順位・名前・合計を空白一つずつで
例 1 · stdin
5
mina 90 85 100
Jun 80 95 100
alex 70 60 50
seo 100 100 75
Bora 60 60 60
stdout
1 Jun 275
1 mina 275
1 seo 275
4 Bora 180
4 alex 180
main.py
入力(stdin)

実行すると、これらの行が順に input()・標準入力に渡されます(実行中に入力を求めません)。

$ 準備完了

コードを入力して解くにはパソコンで開いてください。モバイルでは問題と解答を見られます。

ほかの言語では?言語別の解答を見る · 8 言語の解答

学生一人(名前, 合計)をひとまとめにする方法は言語ごとに違います:Python @dataclass(またはタプル)、Java record Student(String name, int total)、C# record Student(string Name, int Total)、C・C++ struct、JS・TS はオブジェクト { name, total }(TS は interface で形を書きます)。
Craykon にはクラスがないので、学生ごとに 辞書() を一つ(s["name"]、s["total"])作ってリストに入れ、students.並べ替え(合計順) のように比較関数の名前を渡します。
落とし穴は三つ:① 名前のリストと合計のリストを別々に持ち(平行リスト)合計だけ並べ替えると組がずれます。
まとめたまま並べ替えましょう。
② Python で (合計, 名前) を reverse=True で並べると名前まで逆になります(key=lambda s: (-s.total, s.name))。
③ 名前の比較:JS localeCompare は人の辞書順なので "amy" が "Bob" より前になり、C# の既定の文字列比較もカルチャの規則に従うことがあります。
文字コード順は JS <、C# StringComparer.Ordinal、Java compareTo、C strcmp、C++ <。
順位は位置 i + 1 ではなく、前の学生と合計が違うときだけ i + 1 に変えます。

Pythonmain.py · 23 行
import sysfrom dataclasses import dataclass  @dataclassclass Student:    name: str    total: int  lines = sys.stdin.read().split("\n")n = int(lines[0])students = []for line in lines[1:n + 1]:    name, *scores = line.split()    students.append(Student(name, sum(map(int, scores)))) students.sort(key=lambda s: (-s.total, s.name))rank = 0for i, s in enumerate(students):    if i == 0 or s.total != students[i - 1].total:        rank = i + 1    print(rank, s.name, s.total)
JavaScriptmain.js · 16 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const n = Number(lines[0]);const students = [];for (let i = 1; i <= n; i++) {  const [name, ...scores] = lines[i].trim().split(" ");  students.push({ name, total: scores.reduce((sum, x) => sum + Number(x), 0) });}// 이름은 글자 코드 순(< 비교). localeCompare는 대소문자를 사람 사전처럼 섞는다students.sort((a, b) => b.total - a.total || (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));const out = [];let rank = 0;students.forEach((s, i) => {  if (i === 0 || s.total !== students[i - 1].total) rank = i + 1;  out.push(`${rank} ${s.name} ${s.total}`);});console.log(out.join("\n"));
TypeScriptmain.ts · 22 行
import { readFileSync } from "node:fs"; interface Student {  name: string;  total: number;} const lines: string[] = readFileSync(0, "utf8").split("\n");const n: number = Number(lines[0]);const students: Student[] = [];for (let i = 1; i <= n; i++) {  const [name, ...scores] = lines[i].trim().split(" ");  students.push({ name, total: scores.reduce((sum, x) => sum + Number(x), 0) });}students.sort((a, b) => b.total - a.total || (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));const out: string[] = [];let rank = 0;students.forEach((s, i) => {  if (i === 0 || s.total !== students[i - 1].total) rank = i + 1;  out.push(`${rank} ${s.name} ${s.total}`);});console.log(out.join("\n"));
JavaMain.java · 31 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.Comparator;import java.util.List; public class Main {    record Student(String name, int total) {}     public static void main(String[] args) throws IOException {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        int n = Integer.parseInt(in.readLine().trim());        List<Student> students = new ArrayList<>();        for (int i = 0; i < n; i++) {            String[] p = in.readLine().trim().split(" ");            int total = Integer.parseInt(p[1]) + Integer.parseInt(p[2]) + Integer.parseInt(p[3]);            students.add(new Student(p[0], total));        }        // String.compareTo는 글자 코드 순이다(대문자가 소문자보다 먼저)        students.sort(Comparator.comparingInt(Student::total).reversed().thenComparing(Student::name));        StringBuilder out = new StringBuilder();        int rank = 0;        for (int i = 0; i < n; i++) {            Student s = students.get(i);            if (i == 0 || s.total() != students.get(i - 1).total()) rank = i + 1;            out.append(rank).append(' ').append(s.name()).append(' ').append(s.total()).append('\n');        }        System.out.print(out);    }}
C#Main.cs · 27 行
using System;using System.Collections.Generic;using System.Linq; record Student(string Name, int Total); class Program{    static void Main()    {        int n = int.Parse(Console.ReadLine());        var students = new List<Student>();        for (int i = 0; i < n; i++)        {            string[] p = Console.ReadLine().Trim().Split(' ');            students.Add(new Student(p[0], p.Skip(1).Sum(int.Parse)));        }        // 기본 문자열 비교는 문화권 규칙을 따를 수 있어 글자 코드 순(Ordinal)을 밝혀 준다        var sorted = students.OrderByDescending(s => s.Total).ThenBy(s => s.Name, StringComparer.Ordinal).ToList();        int rank = 0;        for (int i = 0; i < sorted.Count; i++)        {            if (i == 0 || sorted[i].Total != sorted[i - 1].Total) rank = i + 1;            Console.WriteLine($"{rank} {sorted[i].Name} {sorted[i].Total}");        }    }}
C++main.cpp · 30 行
#include <algorithm>#include <iostream>#include <string>#include <vector> struct Student {    std::string name;    int total;}; int main() {    int n;    std::cin >> n;    std::vector<Student> students;    for (int i = 0; i < n; i++) {        std::string name;        int k, e, m;        std::cin >> name >> k >> e >> m;        students.push_back({name, k + e + m});    }    std::sort(students.begin(), students.end(), [](const Student& a, const Student& b) {        if (a.total != b.total) return a.total > b.total;        return a.name < b.name;    });    int rank = 0;    for (int i = 0; i < n; i++) {        if (i == 0 || students[i].total != students[i - 1].total) rank = i + 1;        std::cout << rank << ' ' << students[i].name << ' ' << students[i].total << '\n';    }}
Cmain.c · 32 行
#include <stdio.h>#include <stdlib.h>#include <string.h> struct Student {    char name[11];    int total;}; static int by_total_then_name(const void *pa, const void *pb) {    const struct Student *a = pa, *b = pb;    if (a->total != b->total) return b->total - a->total;    return strcmp(a->name, b->name); /* 글자 코드 순 */} int main(void) {    static struct Student s[1000];    int n;    scanf("%d", &n);    for (int i = 0; i < n; i++) {        int k, e, m;        scanf("%10s %d %d %d", s[i].name, &k, &e, &m);        s[i].total = k + e + m;    }    qsort(s, n, sizeof s[0], by_total_then_name);    int rank = 0;    for (int i = 0; i < n; i++) {        if (i == 0 || s[i].total != s[i - 1].total) rank = i + 1;        printf("%d %s %d\n", rank, s[i].name, s[i].total);    }    return 0;}
Craykonmain.cray · 36 行
// 크레이콘에는 클래스가 없어서 학생 한 명을 사전 하나(이름·합계)로 묶는다n = コンソール.行読み().数に();students = [];繰り返す (i = 0; i < n; i++){    p = コンソール.行読み().空白除去().分ける();    s = 辞書();    s["name"] = p[0];    s["total"] = p[1].数に() + p[2].数に() + p[3].数に();    students.追加(s);}students.並べ替え(합계순);rank = 0;繰り返す (i = 0; i < n; i++){    s = students[i];    もし (i == 0 || s["total"] != students[i - 1]["total"])    {        rank = i + 1;    }    コンソール.書く(rank + " " + s["name"] + " " + s["total"]);} // 합계가 큰 것 먼저, 같으면 이름의 글자 코드 순합계순(앞, 뒤){    もし (앞["total"] != 뒤["total"])    {        返す 뒤["total"] - 앞["total"];    }    もし (앞["name"] < 뒤["name"])    {        返す -1;    }    返す 1;}