{ }codelper
자리 맞추기모양 맞춰 출력P0096

성적 표 만들기

첫 줄에 학생 수 n이 주어지고, 다음 n줄에 "이름 국어 영어 수학"이 하나씩 주어진다.
다섯 칸 NAME, KOR, ENG, MATH, AVG로 된 표를 출력하라.
AVG는 세 점수의 평균을 소수 첫째 자리까지 반올림한 값이다(275 / 3 → 91.7, 171 / 3 → 57.0). - 칸마다 너비는 그 칸의 머리글과 그 칸에 들어갈 값들 가운데 가장 긴 것의 글자 수다. - 첫 줄은 머리글, 둘째 줄은 칸마다 너비만큼의 "-"를 "-+-"로 이은 줄, 그다음은 학생마다 한 줄(입력 순서)이다. - 머리글 줄과 학생 줄은 칸 사이에 " | "(빈칸, 세로 막대, 빈칸)를 넣는다.
NAME 칸은 왼쪽 맞춤(뒤에 빈칸), 나머지 칸은 오른쪽 맞춤(앞에 빈칸)이다.
머리글도 같은 규칙을 따른다.

입력
1 ≤ n ≤ 20, 이름은 영어 글자 1~15개, 0 ≤ 각 점수 ≤ 100
출력
n + 2줄의 표
예시 1 · stdin
3
Kim 90 85 100
Alexander 7 100 64
Bo 100 100 100
stdout
NAME      | KOR | ENG | MATH |   AVG
----------+-----+-----+------+------
Kim       |  90 |  85 |  100 |  91.7
Alexander |   7 | 100 |   64 |  57.0
Bo        | 100 | 100 |  100 | 100.0
main.py
입력(stdin)

실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).

$ 준비됐어요

코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.

다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이

먼저 칸마다 너비를 재고(머리글도 넣어서), 그다음 맞춰 써요.
머리글을 빼먹으면 이름이 모두 짧을 때 NAME이 칸을 넘쳐요.
너비를 실행 중에 정하는 방법이 언어마다 달라요.
Python f"{s:<{w}}"·f"{s:>{w}}", C printf("%-*s", w, s)·"%*s"(* 자리에 너비를 넘겨요), C++ std::left/std::right와 std::setw(w), Java String.format("%-" + w + "s", s), JS·TS padEnd/padStart, C# PadRight/PadLeft(C#의 {0,-5}는 너비가 상수여야 해요).
평균은 / 3.0처럼 실수로 나눠야 해요.
C·C++·Java·C#에서 (a + b + c) / 3은 정수 나눗셈이라 91.7이 91이 돼요.
크레이콘은 뒤채우기(너비)/앞채우기(너비)로 맞추고, 소수 한 자리는 글자.소수자리맞추기(합 / 3, 1), 줄은 "-".되풀이(w)와 잇기("-+-")로 만들어요.

Pythonmain.py · 22 줄
n = int(input())headers = ["NAME", "KOR", "ENG", "MATH", "AVG"]rows = []for _ in range(n):    name, *scores = input().split()    a, b, c = map(int, scores)    rows.append([name, str(a), str(b), str(c), f"{(a + b + c) / 3:.1f}"]) # 칸 너비 = 머리글과 그 칸 값들 가운데 가장 긴 것widths = [max(len(r[i]) for r in [headers] + rows) for i in range(5)]  def line(cells):    # 이름은 왼쪽 맞춤, 나머지는 오른쪽 맞춤    parts = [f"{cells[0]:<{widths[0]}}"] + [f"{cells[i]:>{widths[i]}}" for i in range(1, 5)]    return " | ".join(parts)  print(line(headers))print("-+-".join("-" * w for w in widths))for r in rows:    print(line(r))
JavaScriptmain.js · 15 줄
const lines = require("fs").readFileSync(0, "utf8").split("\n");const n = Number(lines[0]);const headers = ["NAME", "KOR", "ENG", "MATH", "AVG"];const rows = [];for (let i = 1; i <= n; i++) {  const [name, ...rest] = lines[i].trim().split(/\s+/);  const [a, b, c] = rest.map(Number);  rows.push([name, String(a), String(b), String(c), ((a + b + c) / 3).toFixed(1)]);}// 칸 너비 = 머리글과 그 칸 값들 가운데 가장 긴 것const widths = headers.map((_, i) => Math.max(...[headers, ...rows].map((r) => r[i].length)));// 이름은 왼쪽 맞춤(padEnd), 나머지는 오른쪽 맞춤(padStart)const line = (cells) => cells.map((s, i) => (i === 0 ? s.padEnd(widths[i]) : s.padStart(widths[i]))).join(" | ");const out = [line(headers), widths.map((w) => "-".repeat(w)).join("-+-"), ...rows.map(line)];console.log(out.join("\n"));
TypeScriptmain.ts · 16 줄
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const n: number = Number(lines[0]);const headers: string[] = ["NAME", "KOR", "ENG", "MATH", "AVG"];const rows: string[][] = [];for (let i = 1; i <= n; i++) {  const [name, ...rest] = lines[i].trim().split(/\s+/);  const [a, b, c] = rest.map(Number);  rows.push([name, String(a), String(b), String(c), ((a + b + c) / 3).toFixed(1)]);}// 칸 너비 = 머리글과 그 칸 값들 가운데 가장 긴 것const widths: number[] = headers.map((_, i) => Math.max(...[headers, ...rows].map((r) => r[i].length)));// 이름은 왼쪽 맞춤(padEnd), 나머지는 오른쪽 맞춤(padStart)const line = (cells: string[]): string => cells.map((s, i) => (i === 0 ? s.padEnd(widths[i]) : s.padStart(widths[i]))).join(" | ");const out: string[] = [line(headers), widths.map((w) => "-".repeat(w)).join("-+-"), ...rows.map(line)];console.log(out.join("\n"));
JavaMain.java · 47 줄
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.List;import java.util.Locale; public class Main {    static int[] widths = new int[5];     public static void main(String[] args) throws IOException {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        int n = Integer.parseInt(in.readLine().trim());        String[] headers = {"NAME", "KOR", "ENG", "MATH", "AVG"};        List<String[]> rows = new ArrayList<>();        rows.add(headers);        for (int i = 0; i < n; i++) {            String[] t = in.readLine().trim().split("\\s+");            int a = Integer.parseInt(t[1]), b = Integer.parseInt(t[2]), c = Integer.parseInt(t[3]);            // Locale.ROOT: 소수점이 쉼표인 지역 설정에서도 91.7로 찍게            String avg = String.format(Locale.ROOT, "%.1f", (a + b + c) / 3.0);            rows.add(new String[] {t[0], t[1], t[2], t[3], avg});        }        // 칸 너비 = 머리글과 그 칸 값들 가운데 가장 긴 것        for (String[] r : rows)            for (int i = 0; i < 5; i++) widths[i] = Math.max(widths[i], r[i].length());        StringBuilder out = new StringBuilder();        for (int k = 0; k < rows.size(); k++) {            out.append(line(rows.get(k))).append('\n');            if (k == 0) {                for (int i = 0; i < 5; i++) {                    if (i > 0) out.append("-+-");                    out.append("-".repeat(widths[i]));                }                out.append('\n');            }        }        System.out.print(out);    }     // 이름은 왼쪽 맞춤(%-Ns), 나머지는 오른쪽 맞춤(%Ns)    static String line(String[] cells) {        StringBuilder sb = new StringBuilder(String.format("%-" + widths[0] + "s", cells[0]));        for (int i = 1; i < 5; i++) sb.append(" | ").append(String.format("%" + widths[i] + "s", cells[i]));        return sb.toString();    }}
C#Main.cs · 30 줄
using System;using System.Collections.Generic;using System.Globalization;using System.Linq; class Program{    static void Main()    {        int n = int.Parse(Console.ReadLine());        string[] headers = { "NAME", "KOR", "ENG", "MATH", "AVG" };        var rows = new List<string[]> { headers };        for (int i = 0; i < n; i++)        {            string[] t = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries);            int a = int.Parse(t[1]), b = int.Parse(t[2]), c = int.Parse(t[3]);            // InvariantCulture: 소수점이 쉼표인 문화권 설정에서도 91.7로 찍게            string avg = ((a + b + c) / 3.0).ToString("F1", CultureInfo.InvariantCulture);            rows.Add(new[] { t[0], t[1], t[2], t[3], avg });        }        // 칸 너비 = 머리글과 그 칸 값들 가운데 가장 긴 것        int[] widths = Enumerable.Range(0, 5).Select(i => rows.Max(r => r[i].Length)).ToArray();        // 이름은 왼쪽 맞춤(PadRight), 나머지는 오른쪽 맞춤(PadLeft)        string Line(string[] cells) =>            string.Join(" | ", cells.Select((s, i) => i == 0 ? s.PadRight(widths[i]) : s.PadLeft(widths[i])));        Console.WriteLine(Line(headers));        Console.WriteLine(string.Join("-+-", widths.Select(w => new string('-', w))));        foreach (var r in rows.Skip(1)) Console.WriteLine(Line(r));    }}
C++main.cpp · 34 줄
#include <algorithm>#include <iomanip>#include <iostream>#include <sstream>#include <string>#include <vector> int main() {    int n;    std::cin >> n;    std::vector<std::vector<std::string>> rows = {{"NAME", "KOR", "ENG", "MATH", "AVG"}};    for (int i = 0; i < n; i++) {        std::string name;        int a, b, c;        std::cin >> name >> a >> b >> c;        std::ostringstream avg;        avg << std::fixed << std::setprecision(1) << (a + b + c) / 3.0;        rows.push_back({name, std::to_string(a), std::to_string(b), std::to_string(c), avg.str()});    }    // 칸 너비 = 머리글과 그 칸 값들 가운데 가장 긴 것    std::vector<std::size_t> widths(5, 0);    for (const auto& r : rows)        for (int i = 0; i < 5; i++) widths[i] = std::max(widths[i], r[i].size());    auto print_row = [&](const std::vector<std::string>& r) {        // 이름은 왼쪽 맞춤(std::left), 나머지는 오른쪽 맞춤(std::right)        std::cout << std::left << std::setw(widths[0]) << r[0];        for (int i = 1; i < 5; i++) std::cout << " | " << std::right << std::setw(widths[i]) << r[i];        std::cout << '\n';    };    print_row(rows[0]);    for (int i = 0; i < 5; i++) std::cout << (i > 0 ? "-+-" : "") << std::string(widths[i], '-');    std::cout << '\n';    for (std::size_t k = 1; k < rows.size(); k++) print_row(rows[k]);}
Cmain.c · 40 줄
#include <stdio.h>#include <string.h> static char cells[21][5][16];static int widths[5]; // 이름은 왼쪽 맞춤(%-*s), 나머지는 오른쪽 맞춤(%*s) — *에 너비를 넘긴다static void print_row(int r) {    printf("%-*s", widths[0], cells[r][0]);    for (int i = 1; i < 5; i++) printf(" | %*s", widths[i], cells[r][i]);    printf("\n");} int main(void) {    int n, a, b, c;    const char *headers[5] = {"NAME", "KOR", "ENG", "MATH", "AVG"};    for (int i = 0; i < 5; i++) strcpy(cells[0][i], headers[i]);    scanf("%d", &n);    for (int r = 1; r <= n; r++) {        scanf("%15s %d %d %d", cells[r][0], &a, &b, &c);        sprintf(cells[r][1], "%d", a);        sprintf(cells[r][2], "%d", b);        sprintf(cells[r][3], "%d", c);        sprintf(cells[r][4], "%.1f", (a + b + c) / 3.0);    }    // 칸 너비 = 머리글과 그 칸 값들 가운데 가장 긴 것    for (int r = 0; r <= n; r++)        for (int i = 0; i < 5; i++) {            int len = strlen(cells[r][i]);            if (len > widths[i]) widths[i] = len;        }    print_row(0);    for (int i = 0; i < 5; i++) {        if (i > 0) printf("-+-");        for (int k = 0; k < widths[i]; k++) putchar('-');    }    printf("\n");    for (int r = 1; r <= n; r++) print_row(r);    return 0;}
Craykonmain.cray · 39 줄
// 이름은 왼쪽 맞춤(뒤채우기), 나머지는 오른쪽 맞춤(앞채우기)줄만들기(cells){    line = cells[0].뒤채우기(widths[0]);    반복 (i = 1; i < 5; i++)    {        line += " | " + cells[i].앞채우기(widths[i]);    }    돌려주기 line;} n = 콘솔.줄읽기().수로변환();rows = [["NAME", "KOR", "ENG", "MATH", "AVG"]];반복 (r = 0; r < n; r++){    t = 콘솔.줄읽기().나누기();    합 = t[1].수로변환() + t[2].수로변환() + t[3].수로변환();    rows.넣기([t[0], t[1], t[2], t[3], 글자.소수자리맞추기(합 / 3, 1)]);}// 칸 너비 = 머리글과 그 칸 값들 가운데 가장 긴 것widths = 새목록(5, 0);각각 (row 에서 rows){    반복 (i = 0; i < 5; i++)    {        widths[i] = 수학.큰수(widths[i], row[i].길이);    }}dashes = [];각각 (w 에서 widths){    dashes.넣기("-".되풀이(w));}콘솔.쓰기(줄만들기(rows[0]));콘솔.쓰기(dashes.잇기("-+-"));반복 (r = 1; r < rows.개수; r++){    콘솔.쓰기(줄만들기(rows[r]));}