{ }codelper
문자열 반복문자열 길이넘침(오버플로)P0175

가로 막대 보고서

항목별 값을 글자로 그린 가로 막대 보고서로 출력한다. 첫 줄에 항목 수 n과 막대의 가장 긴 길이 W가 빈칸 하나로 띄어 주어진다. 다음 n줄에 항목의 이름과 값 v가 빈칸 하나로 띄어 주어진다. 모든 값 가운데 가장 큰 값을 M이라 하자. 항목의 막대 길이는 v × W ÷ M을 소수점 아래를 버린 정수다.
M이 0이면 모든 막대 길이는 0이다. 항목마다 입력 차례대로 한 줄을 출력한다. 줄은 이름, 이름을 가장 긴 이름의 길이에 맞추는 빈칸, " |", 막대 표시, 빈칸 하나, 값 v를 차례로 이은 것이다. 막대 표시는 # 를 막대 길이만큼 쓴 것이다. 다만 v가 0보다 큰데 막대 길이가 0이면, 막대 표시로 .
하나를 쓴다.

입력
1 ≤ n ≤ 500, 1 ≤ W ≤ 100, 0 ≤ v ≤ 10^9(정수).
이름은 길이 1 ~ 20이고 영문자, 숫자, _ 만 쓴다
출력
n줄
예시 1 · stdin
4 20
apple 120
banana 45
kiwi 0
fig 3
stdout
apple  |#################### 120
banana |####### 45
kiwi   | 0
fig    |. 3
예시 2 · stdin
2 5
x 0
y 0
stdout
x | 0
y | 0
main.py
입력(stdin)

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

$ 준비됐어요

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

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

막대 길이는 곱한 다음에 나눠야 해요.
v / M * W처럼 정수 나눗셈을 먼저 하면 가장 큰 값 말고는 거의 다 0이 돼요.
그런데 곱하면 v * W가 10억 × 100 = 1000억까지 가서 int(약 21억)를 넘어요.
C·C++는 long long, Java·C#은 long으로 곱해요.
Python 정수는 끝이 없고, JS·TS·크레이콘의 수는 2^53까지 정수가 정확하니 Math.floor(v * W / M), 수학.내림(v * w / 최대)로 돼요.
M이 0이면 0으로 나누게 되니 먼저 물어요(두 번째 예시).
같은 글자 되풀이는 Python "#" * k, JS·TS·Java "#".repeat(k), C# new string('#', k), C++ std::string(k, '#'), 크레이콘 "#".되풀이(k)예요.
C는 putchar를 k번 돌려요.
이름 맞추기는 길이 재기와 같이 가요.
이름 길이는 Python len(s), JS·TS s.length, Java s.length(), C# s.Length, C strlen(s), C++ s.size(), 크레이콘 s.길이이고, 모자란 빈칸은 (가장 긴 길이 − 이름 길이)개예요.
C printf("%-*s", width, s)는 너비를 인자로 받아 왼쪽 맞춤해 줘요.
반올림하면 첫 예시의 banana가 7.5 → 8이 되니 꼭 버려요.
v가 0보다 큰데 막대가 0일 때 .
를 빠뜨리는 것도 흔한 실수예요.

Pythonmain.py · 16 줄
import sys data = sys.stdin.read().split()n, w = int(data[0]), int(data[1])names = data[2::2][:n]values = [int(x) for x in data[3::2][:n]] width = max(len(s) for s in names)  # 가장 긴 이름에 맞춘다top = max(values)for name, v in zip(names, values):    bar = v * w // top if top > 0 else 0  # 곱한 뒤에 나눈다(먼저 나누면 0이 된다)    if v > 0 and bar == 0:        mark = "."    else:        mark = "#" * bar    print(name + " " * (width - len(name)) + " |" + mark + " " + str(v))
JavaScriptmain.js · 20 줄
const data = require("fs").readFileSync(0, "utf8").trim().split(/\s+/);const n = Number(data[0]);const w = Number(data[1]);const names = [];const values = [];for (let i = 0; i < n; i++) {  names.push(data[2 + 2 * i]);  values.push(Number(data[3 + 2 * i]));}const width = Math.max(...names.map((s) => s.length)); // 가장 긴 이름에 맞춘다const top = Math.max(...values);const out = [];for (let i = 0; i < n; i++) {  const v = values[i];  // 곱한 뒤에 나눈다. v * w는 1000억까지라 Number로 정확하다  const bar = top > 0 ? Math.floor((v * w) / top) : 0;  const mark = v > 0 && bar === 0 ? "." : "#".repeat(bar);  out.push(names[i] + " ".repeat(width - names[i].length) + " |" + mark + " " + v);}console.log(out.join("\n"));
TypeScriptmain.ts · 21 줄
import { readFileSync } from "node:fs";const data: string[] = readFileSync(0, "utf8").trim().split(/\s+/);const n: number = Number(data[0]);const w: number = Number(data[1]);const names: string[] = [];const values: number[] = [];for (let i = 0; i < n; i++) {  names.push(data[2 + 2 * i]);  values.push(Number(data[3 + 2 * i]));}const width: number = Math.max(...names.map((s) => s.length)); // 가장 긴 이름에 맞춘다const top: number = Math.max(...values);const out: string[] = [];for (let i = 0; i < n; i++) {  const v: number = values[i];  // 곱한 뒤에 나눈다. v * w는 1000억까지라 number로 정확하다  const bar: number = top > 0 ? Math.floor((v * w) / top) : 0;  const mark: string = v > 0 && bar === 0 ? "." : "#".repeat(bar);  out.push(names[i] + " ".repeat(width - names[i].length) + " |" + mark + " " + v);}console.log(out.join("\n"));
JavaMain.java · 33 줄
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.StringTokenizer; public class Main {    public static void main(String[] args) throws IOException {        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));        StringTokenizer st = new StringTokenizer(br.readLine());        int n = Integer.parseInt(st.nextToken()), w = Integer.parseInt(st.nextToken());        String[] names = new String[n];        long[] values = new long[n];        int width = 0;        long top = 0;        for (int i = 0; i < n; i++) {            st = new StringTokenizer(br.readLine());            names[i] = st.nextToken();            values[i] = Long.parseLong(st.nextToken());            width = Math.max(width, names[i].length()); // 가장 긴 이름에 맞춘다            top = Math.max(top, values[i]);        }        StringBuilder out = new StringBuilder();        for (int i = 0; i < n; i++) {            long v = values[i];            // v * w는 1000억까지 가서 int로는 넘친다. long으로 곱한 뒤에 나눈다            int bar = top > 0 ? (int) (v * w / top) : 0;            String mark = v > 0 && bar == 0 ? "." : "#".repeat(bar);            out.append(names[i]).append(" ".repeat(width - names[i].length()))               .append(" |").append(mark).append(' ').append(v).append('\n');        }        System.out.print(out);    }}
C#Main.cs · 34 줄
using System;using System.Text; class Program{    static void Main()    {        string[] first = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries);        int n = int.Parse(first[0]), w = int.Parse(first[1]);        var names = new string[n];        var values = new long[n];        int width = 0;        long top = 0;        for (int i = 0; i < n; i++)        {            string[] p = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries);            names[i] = p[0];            values[i] = long.Parse(p[1]);            width = Math.Max(width, names[i].Length); // 가장 긴 이름에 맞춘다            top = Math.Max(top, values[i]);        }        var sb = new StringBuilder();        for (int i = 0; i < n; i++)        {            long v = values[i];            // v * w는 1000억까지 가서 int로는 넘친다. long으로 곱한 뒤에 나눈다            int bar = top > 0 ? (int)(v * w / top) : 0;            string mark = v > 0 && bar == 0 ? "." : new string('#', bar);            sb.Append(names[i]).Append(' ', width - names[i].Length)              .Append(" |").Append(mark).Append(' ').Append(v).Append('\n');        }        Console.Write(sb);    }}
C++main.cpp · 25 줄
#include <algorithm>#include <iostream>#include <string>#include <vector> int main() {    int n, w;    std::cin >> n >> w;    std::vector<std::string> names(n);    std::vector<long long> values(n);    std::size_t width = 0;    long long top = 0;    for (int i = 0; i < n; i++) {        std::cin >> names[i] >> values[i];        width = std::max(width, names[i].size()); // 가장 긴 이름에 맞춘다        top = std::max(top, values[i]);    }    for (int i = 0; i < n; i++) {        long long v = values[i];        // v * w는 1000억까지 가서 int로는 넘친다. long long으로 곱한 뒤에 나눈다        int bar = top > 0 ? static_cast<int>(v * w / top) : 0;        std::string mark = v > 0 && bar == 0 ? "." : std::string(bar, '#');        std::cout << names[i] << std::string(width - names[i].size(), ' ') << " |" << mark << ' ' << v << '\n';    }}
Cmain.c · 27 줄
#include <stdio.h>#include <string.h> int main(void) {    int n, w;    static char names[500][24];    static long long values[500];    scanf("%d %d", &n, &w);    int width = 0;    long long top = 0;    for (int i = 0; i < n; i++) {        scanf("%23s %lld", names[i], &values[i]);        int len = (int)strlen(names[i]);        if (len > width) width = len; /* 가장 긴 이름에 맞춘다 */        if (values[i] > top) top = values[i];    }    for (int i = 0; i < n; i++) {        long long v = values[i];        /* v * w는 1000억까지 가서 int로는 넘친다. long long으로 곱한 뒤에 나눈다 */        int bar = top > 0 ? (int)(v * w / top) : 0;        printf("%-*s |", width, names[i]); /* %-*s: 너비를 인자로 받아 왼쪽 맞춤 */        if (v > 0 && bar == 0) putchar('.');        for (int k = 0; k < bar; k++) putchar('#');        printf(" %lld\n", v);    }    return 0;}
Craykonmain.cray · 30 줄
첫줄 = 콘솔.수들읽기();n = 첫줄[0];w = 첫줄[1];이름들 = [];값들 = [];너비 = 0;최대 = 0;반복 (i = 0; i < n; i += 1){    p = 콘솔.줄읽기().공백제거().나누기();    이름들.넣기(p[0]);    값들.넣기(p[1].수로변환());    너비 = 수학.큰수(너비, p[0].길이); // 가장 긴 이름에 맞춘다    최대 = 수학.큰수(최대, p[1].수로변환());}반복 (i = 0; i < n; i += 1){    v = 값들[i];    막대 = 0;    만약 (최대 > 0)    {        막대 = 수학.내림(v * w / 최대); // 곱한 뒤에 나눈다    }    표시 = "#".되풀이(막대);    만약 (v > 0 && 막대 == 0)    {        표시 = ".";    }    콘솔.쓰기(이름들[i] + " ".되풀이(너비 - 이름들[i].길이) + " |" + 표시 + " " + v);}