{ }codelper
メソッドレコードのリストP0080

勝ち点順位表

チームをクラスとして作り、勝ち点を計算するメソッド points() を置け(勝ち点 = 3 × 勝 + 分、負けは 0 点)。
一行目にチームの数 n、続く n 行に "名前 勝 分 負" が空白一つで区切られて与えられる。
チームオブジェクトのリストを次の順に並べ、チームごとに "名前 勝ち点" を一行ずつ出力せよ:勝ち点の多いチームが先、勝ち点が同じなら勝ちの多いチームが先、勝ち点と勝ちがどちらも同じなら入力で先に出たチームが先。

入力
1 ≤ n ≤ 2000、0 ≤ 勝・分・負 ≤ 100(整数)。
名前は英小文字・数字 1〜10 文字で、同じ名前がまた出ることもある
出力
n 行、各行に名前と勝ち点を空白一つで
例 1 · stdin
5
lions 3 1 2
tigers 2 4 0
bears 3 1 0
hawks 0 5 1
owls 1 2 3
stdout
lions 10
bears 10
tigers 10
owls 5
hawks 5
main.py
入力(stdin)

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

$ 準備完了

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

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

この問題はクラスのある Python・JavaScript・TypeScript・Java・C#・C++ だけを受け付けます(C にはクラスがなく、Craykon はまだクラスを作れません)。
並べ替えの基準はフィールドではなくメソッドの結果です:Python key=lambda t: (t.points(), t.wins)、Java Comparator.comparingInt(Team::points).thenComparingInt(Team::getWins)、C# OrderByDescending(t => t.Points()).ThenByDescending(t => t.Wins)。
最後の規則「同じなら入力順」は安定ソートなら自然に守られます。
Python sort、JS・TS Array.prototype.sort(ES2019 から)、Java List.sort(オブジェクト)、C# LINQ OrderBy は安定で、C# List.Sort と C++ std::sort は安定ではないので、C++ は std::stable_sort を使う必要があります。
落とし穴はあと三つです。
Python で昇順に並べてから reverse() すると同点どうしの順まで逆になります(reverse=True は同点の順を保ちます)。
JS の比較関数が a.points() < b.points() のように true/false を返すと負の数が出ないので並べ替えが崩れます。
b.points() - a.points() のように負・0・正を返しましょう。
Java の reversed() はそれまでにつないだ比較全体を逆にするので、comparingInt(...).reversed().thenComparingInt(...).reversed() は勝ち点がまた昇順になります。

Pythonmain.py · 24 行
import sys  class Team:    def __init__(self, name, wins, draws, losses):        self.name = name        self.wins = wins        self.draws = draws        self.losses = losses     def points(self):        return 3 * self.wins + self.draws  lines = sys.stdin.read().split("\n")n = int(lines[0])teams = []for line in lines[1:n + 1]:    name, w, d, l = line.split()    teams.append(Team(name, int(w), int(d), int(l))) # 정렬은 안정적이라 승점·승수가 같으면 입력 차례가 남는다teams.sort(key=lambda t: (t.points(), t.wins), reverse=True)print("\n".join(f"{t.name} {t.points()}" for t in teams))
JavaScriptmain.js · 24 行
class Team {  constructor(name, wins, draws, losses) {    this.name = name;    this.wins = wins;    this.draws = draws;    this.losses = losses;  }   points() {    return 3 * this.wins + this.draws;  }} const lines = require("fs").readFileSync(0, "utf8").split("\n");const n = Number(lines[0]);const teams = [];for (let i = 1; i <= n; i++) {  const [name, w, d, l] = lines[i].trim().split(" ");  teams.push(new Team(name, Number(w), Number(d), Number(l)));} // 비교 함수는 음수·0·양수를 돌려줘야 한다. sort는 안정적이라 같으면 입력 차례가 남는다teams.sort((a, b) => b.points() - a.points() || b.wins - a.wins);console.log(teams.map((t) => `${t.name} ${t.points()}`).join("\n"));
TypeScriptmain.ts · 31 行
import { readFileSync } from "node:fs"; class Team {  readonly name: string;  readonly wins: number;  readonly draws: number;  readonly losses: number;   constructor(name: string, wins: number, draws: number, losses: number) {    this.name = name;    this.wins = wins;    this.draws = draws;    this.losses = losses;  }   points(): number {    return 3 * this.wins + this.draws;  }} const lines: string[] = readFileSync(0, "utf8").split("\n");const n: number = Number(lines[0]);const teams: Team[] = [];for (let i = 1; i <= n; i++) {  const [name, w, d, l] = lines[i].trim().split(" ");  teams.push(new Team(name, Number(w), Number(d), Number(l)));} // 비교 함수는 음수·0·양수를 돌려줘야 한다. sort는 안정적이라 같으면 입력 차례가 남는다teams.sort((a, b) => b.points() - a.points() || b.wins - a.wins);console.log(teams.map((t) => `${t.name} ${t.points()}`).join("\n"));
JavaMain.java · 40 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.Comparator;import java.util.List; class Team {    private final String name;    private final int wins, draws, losses;     Team(String name, int wins, int draws, int losses) {        this.name = name;        this.wins = wins;        this.draws = draws;        this.losses = losses;    }     String getName() { return name; }    int getWins() { return wins; }    int points() { return 3 * wins + draws; }} public class Main {    public static void main(String[] args) throws IOException {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        int n = Integer.parseInt(in.readLine().trim());        List<Team> teams = new ArrayList<>();        for (int i = 0; i < n; i++) {            String[] p = in.readLine().trim().split(" ");            teams.add(new Team(p[0], Integer.parseInt(p[1]), Integer.parseInt(p[2]), Integer.parseInt(p[3])));        }         // List.sort(객체)는 안정 정렬이라 같으면 입력 차례가 남는다        teams.sort(Comparator.comparingInt(Team::points).thenComparingInt(Team::getWins).reversed());        StringBuilder out = new StringBuilder();        for (Team t : teams) out.append(t.getName()).append(' ').append(t.points()).append('\n');        System.out.print(out);    }}
C#Main.cs · 42 行
using System;using System.Collections.Generic;using System.Linq;using System.Text; class Team{    public string Name { get; }    public int Wins { get; }    public int Draws { get; }    public int Losses { get; }     public Team(string name, int wins, int draws, int losses)    {        Name = name;        Wins = wins;        Draws = draws;        Losses = losses;    }     public int Points() => 3 * Wins + Draws;} class Program{    static void Main()    {        int n = int.Parse(Console.ReadLine());        var teams = new List<Team>();        for (int i = 0; i < n; i++)        {            string[] p = Console.ReadLine().Trim().Split(' ');            teams.Add(new Team(p[0], int.Parse(p[1]), int.Parse(p[2]), int.Parse(p[3])));        }         // List.Sort는 안정 정렬이 아니다. OrderBy는 안정이라 같으면 입력 차례가 남는다        var ranked = teams.OrderByDescending(t => t.Points()).ThenByDescending(t => t.Wins);        var sb = new StringBuilder();        foreach (var t in ranked) sb.Append($"{t.Name} {t.Points()}\n");        Console.Write(sb);    }}
C++main.cpp · 39 行
#include <algorithm>#include <iostream>#include <string>#include <utility>#include <vector> class Team {public:    Team(std::string name, int wins, int draws, int losses)        : name_(std::move(name)), wins_(wins), draws_(draws), losses_(losses) {}     const std::string& name() const { return name_; }    int wins() const { return wins_; }    int points() const { return 3 * wins_ + draws_; } private:    std::string name_;    int wins_, draws_, losses_;}; int main() {    std::ios::sync_with_stdio(false);    int n;    std::cin >> n;    std::vector<Team> teams;    for (int i = 0; i < n; i++) {        std::string name;        int w, d, l;        std::cin >> name >> w >> d >> l;        teams.emplace_back(name, w, d, l);    }     // std::sort는 안정 정렬이 아니다. stable_sort라야 같으면 입력 차례가 남는다    std::stable_sort(teams.begin(), teams.end(), [](const Team& a, const Team& b) {        if (a.points() != b.points()) return a.points() > b.points();        return a.wins() > b.wins();    });    for (const Team& t : teams) std::cout << t.name() << ' ' << t.points() << '\n';}