{ }codelper
줄 안 바꾸고 출력타입 바꾸기P0164

기온 띠 그림

기상 관측소가 d일 동안 하루에 h번씩 기온을 쟀다. 기온은 0.1도 단위의 정수로 기록되어 있다(-35는 -3.5도). 첫 줄에 d와 h가, 다음 d줄에 그날의 기온 h개가 빈칸으로 나뉘어 주어진다. 모든 기록 중 가장 낮은 값을 lo, 가장 높은 값을 hi라 하자. 기온 x의 칸 번호는 (x − lo) × 9 ÷ (hi − lo + 1)에서 소수 부분을 버린 정수이고, 0부터 8까지다. 칸 번호 0~8에는 차례로 글자 . : - = + * # % @를 쓴다. 날마다 한 줄에, 그날의 기온을 잰 차례대로 칸 글자 h개를 사이 빈칸 없이 이어 출력하라. 마지막 줄에는 lo와 hi를 도 단위로 소수 첫째 자리까지 빈칸 하나로 띄워 출력하라(-35는 -3.5, 0은 0.0, 200은 20.0). 기온은 모두 0.1도 단위라서 이 두 값은 소수 첫째 자리까지 정확히 나타난다.

입력
1 ≤ d ≤ 100, 1 ≤ h ≤ 48, -400 ≤ 기온 ≤ 500(정수)
출력
d줄의 칸 글자(줄마다 h글자), 마지막 줄 "lo hi"(도 단위, 소수 한 자리)
예시 1 · stdin
2 5
-35 -10 42 118 97
12 60 155 203 140
stdout
..-*+
:=%@#
-3.5 20.3
main.py
입력(stdin)

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

$ 준비됐어요

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

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

수의 타입이 바뀌는 곳이 두 군데예요.
① 칸 번호: C·C++·Java·C#에서 int끼리 /는 몫만 남으니 곱하기를 먼저 해야 해요.
(x - lo) / width * 9라고 쓰면 x - lo가 늘 width보다 작아서 모두 0, 곧 모두 .이 돼요.
Python 3·JS·TS·크레이콘의 /는 실수를 주니 칸 번호로 쓰려면 정수로 바꿔야 해요: Python //(그냥 /면 SCALE[2.0]에서 TypeError), JS·TS Math.floor(안 하면 SCALE[2.5]가 undefined), 크레이콘 수학.내림.
나누는 수는 hi - lo + 1이에요.
+ 1을 빼면 가장 높은 값이 없는 9번 칸이 되고, 값이 모두 같으면 0으로 나눠요.
칸은 날마다가 아니라 전체의 lo·hi로 정해요.
② 0.1도 정수를 도로 쓰기: 실수로 바꿔 나누는 것(lo / 10.0, Python·JS lo / 10)이 안전해요.
몫과 나머지로 "정수.한자리"를 만들면 음수에서 틀려요: C·C++·Java·C#의 -5 / 10은 0이라(JS Math.trunc(-5 / 10)도 0으로 찍혀요) -0.5가 0.5가 되고, Python -5 // 10은 -1, -5 % 10은 5라서 -1.5가 돼요.
소수 한 자리는 Python f"{x:.1f}", JS·TS toFixed(1), C printf("%.1f"), C++ std::fixed << std::setprecision(1), Java String.format(Locale.ROOT, "%.1f", x), C# ToString("F1", CultureInfo.InvariantCulture), 크레이콘 글자.소수자리맞추기(x, 1)예요.
줄을 바꾸지 않고 한 글자씩 쓰기: Python print(c, end=""), JS·TS process.stdout.write(c)(console.log는 늘 줄을 바꿔요), Java System.out.print(여러 번 부르면 느려서 PrintWriter에 모아요), C# Console.Write(여기서는 StreamWriter로 모아요), C putchar, C++ std::cout << c, 크레이콘 콘솔.이어쓰기.
줄 끝에는 따로 줄 바꿈을 써요.
C에서 한 줄을 모아 printf(row)로 찍으면 안 돼요.
글자 %를 서식으로 읽어서 %%가 % 하나가 돼요.
fputs(row, stdout)이나 printf("%s", row)를 써요.

Pythonmain.py · 14 줄
SCALE = ".:-=+*#%@"  # 낮은 칸부터 높은 칸까지 아홉 글자 d, h = map(int, input().split())days = [list(map(int, input().split())) for _ in range(d)]lo = min(min(day) for day in days)hi = max(max(day) for day in days)width = hi - lo + 1for day in days:    for x in day:        # // 로 나눠야 정수다. / 는 실수라서 SCALE[2.5]처럼 칸 번호로 쓸 수 없다        print(SCALE[(x - lo) * 9 // width], end="")    print()# 0.1도 단위 정수를 실수로 바꿔 10으로 나눈다: -5 → -0.5print(f"{lo / 10:.1f} {hi / 10:.1f}")
JavaScriptmain.js · 16 줄
const SCALE = ".:-=+*#%@"; // 낮은 칸부터 높은 칸까지 아홉 글자const nums = require("fs").readFileSync(0, "utf8").trim().split(/\s+/).map(Number);const [d, h] = nums;const temps = nums.slice(2);const lo = Math.min(...temps);const hi = Math.max(...temps);const width = hi - lo + 1;for (let i = 0; i < d; i++) {  for (let j = 0; j < h; j++) {    const x = temps[i * h + j];    // / 는 실수라서 Math.floor로 정수 칸 번호를 만든다(SCALE[2.5]는 undefined)    process.stdout.write(SCALE[Math.floor(((x - lo) * 9) / width)]); // 줄을 바꾸지 않고 쓴다  }  process.stdout.write("\n");}console.log(`${(lo / 10).toFixed(1)} ${(hi / 10).toFixed(1)}`);
TypeScriptmain.ts · 17 줄
import { readFileSync } from "node:fs";const SCALE = ".:-=+*#%@"; // 낮은 칸부터 높은 칸까지 아홉 글자const nums: number[] = readFileSync(0, "utf8").trim().split(/\s+/).map(Number);const [d, h] = nums;const temps: number[] = nums.slice(2);const lo: number = Math.min(...temps);const hi: number = Math.max(...temps);const width: number = hi - lo + 1;for (let i = 0; i < d; i++) {  for (let j = 0; j < h; j++) {    const x: number = temps[i * h + j];    // / 는 실수라서 Math.floor로 정수 칸 번호를 만든다    process.stdout.write(SCALE[Math.floor(((x - lo) * 9) / width)]); // 줄을 바꾸지 않고 쓴다  }  process.stdout.write("\n");}console.log(`${(lo / 10).toFixed(1)} ${(hi / 10).toFixed(1)}`);
JavaMain.java · 36 줄
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.util.Locale;import java.util.StringTokenizer; public class Main {    static final String SCALE = ".:-=+*#%@"; // 낮은 칸부터 높은 칸까지 아홉 글자     public static void main(String[] args) throws IOException {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        StringTokenizer st = new StringTokenizer(in.readLine());        int d = Integer.parseInt(st.nextToken()), h = Integer.parseInt(st.nextToken());        int[][] t = new int[d][h];        int lo = Integer.MAX_VALUE, hi = Integer.MIN_VALUE;        for (int i = 0; i < d; i++) {            st = new StringTokenizer(in.readLine());            for (int j = 0; j < h; j++) {                t[i][j] = Integer.parseInt(st.nextToken());                lo = Math.min(lo, t[i][j]);                hi = Math.max(hi, t[i][j]);            }        }        int width = hi - lo + 1;        PrintWriter out = new PrintWriter(System.out); // print를 여러 번 해도 한 번에 내보낸다        for (int[] day : t) {            // int끼리는 몫만 남는다: 곱하기를 먼저 해야 한다((x - lo) / width * 9는 늘 0)            for (int x : day) out.print(SCALE.charAt((x - lo) * 9 / width));            out.println();        }        // int를 double로 바꿔 나눈다: -5 / 10은 0이지만 -5 / 10.0은 -0.5        out.println(String.format(Locale.ROOT, "%.1f %.1f", lo / 10.0, hi / 10.0));        out.flush();    }}
C#Main.cs · 31 줄
using System;using System.Globalization;using System.IO;using System.Linq; class Program{    const string Scale = ".:-=+*#%@"; // 낮은 칸부터 높은 칸까지 아홉 글자     static void Main()    {        int[] dh = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();        int d = dh[0];        var days = new int[d][];        for (int i = 0; i < d; i++)            days[i] = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();        int lo = days.Min(r => r.Min()), hi = days.Max(r => r.Max());        int width = hi - lo + 1;        var out_ = new StreamWriter(Console.OpenStandardOutput()); // Write를 여러 번 해도 한 번에 내보낸다        foreach (int[] day in days)        {            // int끼리는 몫만 남는다: 곱하기를 먼저            foreach (int x in day) out_.Write(Scale[(x - lo) * 9 / width]);            out_.Write('\n');        }        // int를 double로 바꿔 나눈다: -5 / 10은 0, -5 / 10.0은 -0.5        var inv = CultureInfo.InvariantCulture;        out_.Write((lo / 10.0).ToString("F1", inv) + " " + (hi / 10.0).ToString("F1", inv) + "\n");        out_.Flush();    }}
C++main.cpp · 28 줄
#include <algorithm>#include <iomanip>#include <iostream>#include <string>#include <vector> int main() {    const std::string SCALE = ".:-=+*#%@"; // 낮은 칸부터 높은 칸까지 아홉 글자    std::ios::sync_with_stdio(false);    int d, h;    std::cin >> d >> h;    std::vector<std::vector<int>> t(d, std::vector<int>(h));    int lo = 1000, hi = -1000;    for (auto& day : t)        for (int& x : day) {            std::cin >> x;            lo = std::min(lo, x);            hi = std::max(hi, x);        }    int width = hi - lo + 1;    for (const auto& day : t) {        // int끼리는 몫만 남는다: 곱하기를 먼저. << 는 줄을 바꾸지 않는다        for (int x : day) std::cout << SCALE[(x - lo) * 9 / width];        std::cout << '\n';    }    // int를 double로 바꿔 나눈다: -5 / 10은 0이지만 -5 / 10.0은 -0.5    std::cout << std::fixed << std::setprecision(1) << lo / 10.0 << ' ' << hi / 10.0 << '\n';}
Cmain.c · 25 줄
#include <stdio.h> static const char SCALE[] = ".:-=+*#%@"; /* 낮은 칸부터 높은 칸까지 아홉 글자 */static int t[100][48]; int main(void) {    int d, h;    scanf("%d %d", &d, &h);    int lo = 1000, hi = -1000;    for (int i = 0; i < d; i++)        for (int j = 0; j < h; j++) {            scanf("%d", &t[i][j]);            if (t[i][j] < lo) lo = t[i][j];            if (t[i][j] > hi) hi = t[i][j];        }    int width = hi - lo + 1;    for (int i = 0; i < d; i++) {        /* int끼리는 몫만 남는다: 곱하기를 먼저. putchar는 줄을 바꾸지 않는다 */        for (int j = 0; j < h; j++) putchar(SCALE[(t[i][j] - lo) * 9 / width]);        putchar('\n');    }    /* int를 double로 바꿔 나눈다: -5 / 10은 0이지만 -5 / 10.0은 -0.5 */    printf("%.1f %.1f\n", lo / 10.0, hi / 10.0);    return 0;}
Craykonmain.cray · 30 줄
// 낮은 칸부터 높은 칸까지 아홉 글자눈금 = ".:-=+*#%@";첫줄 = 콘솔.수들읽기();d = 첫줄[0];날들 = [];반복 (i = 0; i < d; i++){    날들.넣기(콘솔.수들읽기());}가장낮음 = 날들[0][0];가장높음 = 날들[0][0];각각 (날 에서 날들){    각각 (x 에서 날)    {        가장낮음 = 수학.작은수(가장낮음, x);        가장높음 = 수학.큰수(가장높음, x);    }}폭 = 가장높음 - 가장낮음 + 1;각각 (날 에서 날들){    각각 (x 에서 날)    {        // / 는 소수까지 나눈다: 칸 번호는 수학.내림으로 정수로        콘솔.이어쓰기(눈금[수학.내림((x - 가장낮음) * 9 / 폭)]);    }    콘솔.쓰기("");}콘솔.쓰기(글자.소수자리맞추기(가장낮음 / 10, 1) + " " + 글자.소수자리맞추기(가장높음 / 10, 1));