파일 목록의 크기(바이트)를 사람이 읽기 쉬운 단위로 바꾼다.
첫 줄에 파일 수 n이 주어진다.
다음 n줄에는 한 줄에 파일 이름, 빈칸 하나, 크기 s가 차례로 주어진다.
파일 이름에는 빈칸이 들어 있을 수 있다.
단위는 B, KiB, MiB, GiB, TiB이고, 1 KiB = 1024 B, 1 MiB = 1024 KiB, 1 GiB = 1024 MiB, 1 TiB = 1024 GiB다.
s가 1024보다 작으면 "s B"로 쓴다(예: 1023 B).
그렇지 않으면 1 단위의 바이트 수가 s 이하인 가장 큰 단위를 고르고, s를 그 단위로 나눈 값을 소수 첫째 자리까지 반올림해 쓴다.
반올림은 나눈 정확한 값에 가장 가까운 소수 한 자리 수로 하고, 두 수의 정확히 가운데이면 큰 쪽으로 한다(1.25 → 1.3, 1.249… → 1.2).
반올림한 값이 1024.0이 되면 한 단계 큰 단위로 바꿔 1.0으로 쓴다(TiB는 더 큰 단위가 없지만 이 범위에서는 1024.0 TiB가 나오지 않는다).
B가 아닌 단위에서는 값을 언제나 소수 한 자리로 쓴다(예: 1.0 KiB, 4.5 GiB).
파일마다 한 줄에 "이름: 크기"를 출력하라.
입력
1 ≤ n ≤ 1,000, 0 ≤ s ≤ 100,000,000,000,000 (10^14), 이름은 1~40글자로 영어 글자·숫자·점·밑줄·빼기표·빈칸으로 되어 있고, 빈칸으로 시작하거나 끝나지 않으며 빈칸이 둘 이어지지 않음
출력
파일마다 "이름: 크기" 한 줄
예시 1 · stdin
5
notes.txt 1023
icon.png 1024
My Photo 2024.jpg 1280
backup part 1.zip 1048575
movie.mkv 4831838208
stdout
notes.txt: 1023 B
icon.png: 1.0 KiB
My Photo 2024.jpg: 1.3 KiB
backup part 1.zip: 1.0 MiB
movie.mkv: 4.5 GiB
main.py
오류 목록00F8 ↓ · ⇧F8 ↑
입력(stdin)
실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).
$ 준비됐어요
코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.
다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이
줄 읽기 함정부터 봐요. 이름에 빈칸이 있으니 낱말 단위로 읽으면 안 되고, 줄 전체를 읽은 뒤 마지막 빈칸에서 잘라요. Python input().rsplit(" ", 1), JS·TS lastIndexOf(" "), Java BufferedReader.readLine()과 lastIndexOf, C# Console.ReadLine()과 LastIndexOf, C fgets와 strrchr(끝의 줄바꿈은 지워요), C++ std::getline과 rfind예요. C++ std::cin >> name과 C scanf("%s")는 빈칸에서 멈춰 "My Photo 2024.jpg"가 "My"가 돼요. Java Scanner로 nextInt() 뒤에 nextLine()을 부르면 첫 줄에 남은 줄바꿈만 읽어 빈 문자열이 나와요. 크레이콘 콘솔.줄읽기()는 줄 전체를 돌려주는데 마지막 빈칸을 찾는 멤버가 없어서, 나누기(" ")로 쪼갠 뒤 마지막 조각을 크기로 쓰고 나머지를 부분목록과 잇기(" ")로 다시 붙여요(이름 안의 빈칸이 하나씩이라 원래 이름이 돌아와요). 거듭제곱: 1024^k는 Python·JS·TS 1024 ** k, Java·C# Math.pow/Math.Pow, C pow, C++ std::pow인데 뒤의 넷은 double을 돌려줘요. 2의 거듭제곱이라 값은 정확하지만, 정수로 계산할 거라면 1024를 곱해 가는 편이 깔끔해요(크레이콘은 거듭제곱 연산자가 없어서 곱해 가요). 1024^4 = 2^40이라 32비트 int로는 넘쳐서 Java·C#은 long, C·C++은 long long이에요. 반올림 함정: 1280 B는 정확히 1.25 KiB예요. Python f"{x:.1f}"·round(x, 1)과 C·C++ printf("%.1f")는 정확한 가운데를 짝수 쪽으로 보내 1.2를 내고, JS toFixed(1)은 1.3을 내요. 이렇게 언어마다 다르니 반올림을 정수로 직접 해요. 값 × 10을 반올림한 수는 (20 × s + d) ÷ (2 × d)의 몫(d = 1024^k)이고, 가운데는 늘 올라가요. d가 2의 거듭제곱이라 JS·TS·크레이콘의 실수 나눗셈도 이 몫을 정확히 내요. 마지막 함정은 1048575 B처럼 1023.999… KiB가 반올림으로 1024.0이 되는 경우예요. 이때 단위를 하나 올려 1.0 MiB로 써야 해요.
Pythonmain.py · 23 줄
UNITS = ["B", "KiB", "MiB", "GiB", "TiB"]def human(s): if s < 1024: return f"{s} B" k = 1 while k < 4 and 1024 ** (k + 1) <= s: k += 1 d = 1024 ** k # 정수 거듭제곱이라 정확하다 t = (20 * s + d) // (2 * d) # 소수 첫째 자리까지 반올림한 값 × 10 (0.5는 올림) if t >= 10240 and k < 4: # 1024.0이 되면 다음 단위로 k += 1 d *= 1024 t = (20 * s + d) // (2 * d) return f"{t // 10}.{t % 10} {UNITS[k]}"n = int(input())for _ in range(n): line = input() name, size = line.rsplit(" ", 1) # 이름에 빈칸이 있을 수 있어 마지막 빈칸에서 자른다 print(f"{name}: {human(int(size))}")
JavaScriptmain.js · 24 줄
const lines = require("fs").readFileSync(0, "utf8").split("\n");const UNITS = ["B", "KiB", "MiB", "GiB", "TiB"];const human = (s) => { if (s < 1024) return s + " B"; let k = 1; while (k < 4 && 1024 ** (k + 1) <= s) k++; let d = 1024 ** k; // 2의 거듭제곱이라 number로 정확하다 let t = Math.floor((20 * s + d) / (2 * d)); // 소수 첫째 자리까지 반올림한 값 × 10 (0.5는 올림) if (t >= 10240 && k < 4) { // 1024.0이 되면 다음 단위로 k++; d *= 1024; t = Math.floor((20 * s + d) / (2 * d)); } return Math.floor(t / 10) + "." + (t % 10) + " " + UNITS[k];};const n = Number(lines[0]);const out = [];for (let i = 1; i <= n; i++) { const line = lines[i]; const cut = line.lastIndexOf(" "); // 이름에 빈칸이 있을 수 있어 마지막 빈칸에서 자른다 out.push(line.slice(0, cut) + ": " + human(Number(line.slice(cut + 1))));}console.log(out.join("\n"));
TypeScriptmain.ts · 25 줄
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const UNITS: string[] = ["B", "KiB", "MiB", "GiB", "TiB"];const human = (s: number): string => { if (s < 1024) return s + " B"; let k = 1; while (k < 4 && 1024 ** (k + 1) <= s) k++; let d: number = 1024 ** k; // 2의 거듭제곱이라 number로 정확하다 let t: number = Math.floor((20 * s + d) / (2 * d)); // 소수 첫째 자리까지 반올림한 값 × 10 (0.5는 올림) if (t >= 10240 && k < 4) { // 1024.0이 되면 다음 단위로 k++; d *= 1024; t = Math.floor((20 * s + d) / (2 * d)); } return Math.floor(t / 10) + "." + (t % 10) + " " + UNITS[k];};const n = Number(lines[0]);const out: string[] = [];for (let i = 1; i <= n; i++) { const line: string = lines[i]; const cut: number = line.lastIndexOf(" "); // 이름에 빈칸이 있을 수 있어 마지막 빈칸에서 자른다 out.push(line.slice(0, cut) + ": " + human(Number(line.slice(cut + 1))));}console.log(out.join("\n"));
JavaMain.java · 35 줄
import java.io.BufferedReader;import java.io.InputStreamReader;public class Main { static final String[] UNITS = {"B", "KiB", "MiB", "GiB", "TiB"}; static String human(long s) { if (s < 1024) return s + " B"; int k = 1; long d = 1024; while (k < 4 && d * 1024 <= s) { // 1024를 곱해 가며 거듭제곱(long이라 넘치지 않는다) d *= 1024; k++; } long t = (20 * s + d) / (2 * d); // 소수 첫째 자리까지 반올림한 값 × 10 (0.5는 올림) if (t >= 10240 && k < 4) { // 1024.0이 되면 다음 단위로 k++; d *= 1024; t = (20 * s + d) / (2 * d); } return t / 10 + "." + t % 10 + " " + UNITS[k]; } public static void main(String[] args) throws Exception { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(in.readLine().trim()); StringBuilder out = new StringBuilder(); for (int i = 0; i < n; i++) { String line = in.readLine(); // 줄 전체를 읽는다 int cut = line.lastIndexOf(' '); // 이름에 빈칸이 있을 수 있어 마지막 빈칸에서 자른다 out.append(line, 0, cut).append(": ").append(human(Long.parseLong(line.substring(cut + 1)))).append('\n'); } System.out.print(out); }}
C#Main.cs · 40 줄
using System;using System.Text;class Program{ static readonly string[] Units = { "B", "KiB", "MiB", "GiB", "TiB" }; static string Human(long s) { if (s < 1024) return s + " B"; int k = 1; long d = 1024; while (k < 4 && d * 1024 <= s) // 1024를 곱해 가며 거듭제곱(long이라 넘치지 않는다) { d *= 1024; k++; } long t = (20 * s + d) / (2 * d); // 소수 첫째 자리까지 반올림한 값 × 10 (0.5는 올림) if (t >= 10240 && k < 4) // 1024.0이 되면 다음 단위로 { k++; d *= 1024; t = (20 * s + d) / (2 * d); } return $"{t / 10}.{t % 10} {Units[k]}"; } static void Main() { int n = int.Parse(Console.ReadLine()); var sb = new StringBuilder(); for (int i = 0; i < n; i++) { string line = Console.ReadLine(); // 줄 전체를 읽는다 int cut = line.LastIndexOf(' '); // 이름에 빈칸이 있을 수 있어 마지막 빈칸에서 자른다 sb.Append(line, 0, cut).Append(": ").Append(Human(long.Parse(line.Substring(cut + 1)))).Append('\n'); } Console.Write(sb); }}
C++main.cpp · 32 줄
#include <iostream>#include <string>const std::string UNITS[] = {"B", "KiB", "MiB", "GiB", "TiB"};std::string human(long long s) { if (s < 1024) return std::to_string(s) + " B"; int k = 1; long long d = 1024; while (k < 4 && d * 1024 <= s) { // 1024를 곱해 가며 거듭제곱(long long이라 넘치지 않는다) d *= 1024; k++; } long long t = (20 * s + d) / (2 * d); // 소수 첫째 자리까지 반올림한 값 × 10 (0.5는 올림) if (t >= 10240 && k < 4) { // 1024.0이 되면 다음 단위로 k++; d *= 1024; t = (20 * s + d) / (2 * d); } return std::to_string(t / 10) + "." + std::to_string(t % 10) + " " + UNITS[k];}int main() { std::string line; std::getline(std::cin, line); int n = std::stoi(line); for (int i = 0; i < n; i++) { std::getline(std::cin, line); // 줄 전체를 읽는다(>>는 빈칸에서 멈춘다) auto cut = line.rfind(' '); // 이름에 빈칸이 있을 수 있어 마지막 빈칸에서 자른다 std::cout << line.substr(0, cut) << ": " << human(std::stoll(line.substr(cut + 1))) << '\n'; }}
Cmain.c · 40 줄
#include <stdio.h>#include <stdlib.h>#include <string.h>static const char* UNITS[] = {"B", "KiB", "MiB", "GiB", "TiB"};void print_human(long long s) { if (s < 1024) { printf("%lld B\n", s); return; } int k = 1; long long d = 1024; while (k < 4 && d * 1024 <= s) { /* 1024를 곱해 가며 거듭제곱(long long이라 넘치지 않는다) */ d *= 1024; k++; } long long t = (20 * s + d) / (2 * d); /* 소수 첫째 자리까지 반올림한 값 × 10 (0.5는 올림) */ if (t >= 10240 && k < 4) { /* 1024.0이 되면 다음 단위로 */ k++; d *= 1024; t = (20 * s + d) / (2 * d); } printf("%lld.%lld %s\n", t / 10, t % 10, UNITS[k]);}int main(void) { char line[128]; fgets(line, sizeof line, stdin); int n = atoi(line); for (int i = 0; i < n; i++) { fgets(line, sizeof line, stdin); /* 줄 전체를 읽는다(끝의 줄바꿈까지) */ line[strcspn(line, "\n")] = '\0'; char* cut = strrchr(line, ' '); /* 이름에 빈칸이 있을 수 있어 마지막 빈칸에서 자른다 */ *cut = '\0'; printf("%s: ", line); print_human(atoll(cut + 1)); } return 0;}
Craykonmain.cray · 40 줄
UNITS = ["B", "KiB", "MiB", "GiB", "TiB"];반올림열배(s, d){ // 소수 첫째 자리까지 반올림한 값 × 10 (0.5는 올림). d가 2의 거듭제곱이라 나눗셈이 정확하다 돌려주기 수학.몫(20 * s + d, 2 * d);}사람단위(s){ 만약 (s < 1024) { 돌려주기 s + " B"; } k = 1; d = 1024; 동안 (k < 4 && d * 1024 <= s) { d *= 1024; // 거듭제곱 연산자가 없으니 1024를 곱해 간다 k += 1; } t = 반올림열배(s, d); 만약 (t >= 10240 && k < 4) { k += 1; // 1024.0이 되면 다음 단위로 d *= 1024; t = 반올림열배(s, d); } 돌려주기 수학.몫(t, 10) + "." + t % 10 + " " + UNITS[k];}n = 콘솔.줄읽기().수로변환();반복 (i = 0; i < n; i++){ // 이름에 빈칸이 있을 수 있어 줄 전체를 읽고 마지막 조각을 크기로 쓴다(이름 안의 빈칸은 하나씩) 조각 = 콘솔.줄읽기().나누기(" "); 크기 = 조각[조각.개수 - 1].수로변환(); 이름 = 조각.부분목록(0, 조각.개수 - 1).잇기(" "); 콘솔.쓰기(이름 + ": " + 사람단위(크기));}