글자로 자를 그려 출력한다.
첫 줄에 자의 길이 n과 큰 눈금 간격 k가 빈칸 하나로 띄어 주어진다.
자에는 0부터 n까지 n + 1개의 칸이 있고, 칸 번호는 왼쪽부터 0, 1, 2, …, n이다.
첫째 줄은 눈금 줄이다. 정확히 n + 1글자이고, 칸 c의 글자는 c가 k의 배수면 |, 아니면 . 이다.
둘째 줄은 숫자 줄이다. 0, k, 2k, 3k, …처럼 n 이하인 k의 배수 m을 작은 것부터 차례로 보며, m을 십진수로 칸 m부터 오른쪽으로 쓰려고 한다.
m을 쓰면 차지하는 마지막 칸은 m + (m의 자릿수) − 1이다. 이 칸이 n보다 크면 m을 쓰지 않는다.
또 앞에서 이미 쓴 숫자가 있으면, 그 숫자의 마지막 칸과 칸 m 사이에 빈칸이 적어도 하나 있어야 한다. 그렇지 않으면 m을 쓰지 않는다.
쓰지 않고 건너뛴 숫자는 그 뒤의 판단에 아무 영향을 주지 않는다.
숫자를 쓰지 않은 칸은 빈칸이고, 숫자 줄의 맨 끝 빈칸은 출력하지 않는다.
셋째 줄에는 숫자 줄에 쓴 숫자의 개수를 출력한다.
입력
1 ≤ k ≤ n ≤ 5000
출력
세 줄
예시 1 · stdin
25 5
stdout
|....|....|....|....|....|
0 5 10 15 20
5
예시 2 · stdin
12 1
stdout
|||||||||||||
0 2 4 6 8 10
6
main.py
오류 목록00F8 ↓ · ⇧F8 ↑
입력(stdin)
실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).
$ 준비됐어요
코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.
다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이
눈금은 k씩 건너뛰는 반복이에요. Python range(0, n + 1, k)는 끝을 넣지 않아서 n + 1까지 줘야 칸 n이 들어가요. 나머지 언어는 for (m = 0; m <= n; m += k), 크레이콘은 반복 (m = 0; m <= n; m += k)예요. 눈금 줄을 c < n으로 돌면 n글자만 나와서 첫 예시의 맨 끝 | 가 빠져요. 숫자 줄은 왼쪽부터 차례로 붙여 가면 지금 길이가 곧 다음 빈 칸 번호라서, '빈칸이 하나 이상'은 m > 지금 길이, 모자란 빈칸은 m - 지금 길이개예요. 건너뛴 숫자의 끝 칸을 '앞 숫자'로 기억하면 두 번째 예시에서 2, 4, 6도 빠져요. 맞는지는 <=이라서 <로 쓰면 n = 9, k = 9의 9가 사라져요. 자릿수는 수를 문자열로 바꿔 길이를 재요. Python len(str(m)), JS·TS String(m).length, Java Integer.toString(m).length(), C# m.ToString().Length, C++ std::to_string(m).size(), 크레이콘 ("" + m).길이예요. C는 sprintf가 돌려주는 쓴 글자 수를 쓰면 돼요. 문자열을 이어 붙이는 방법도 달라요. Java·C#은 반복문에서 +=를 하면 매번 새 문자열을 복사하니 StringBuilder를 써요(C#은 Append(' ', 개수)로 빈칸을 한 번에 붙여요). Python·JS·TS·C++ std::string·크레이콘은 +=로 충분하고, C는 글자 배열에 채운 뒤 끝에 '\0'을 넣어요. C++ size()는 부호 없는 수라서 m > labels.size()처럼 섞어 비교하기 전에 int로 바꿔 두는 게 안전해요.
Pythonmain.py · 19 줄
n, k = map(int, input().split())# 눈금 줄: 칸 0 ~ n, 모두 n + 1글자marks = "".join("|" if c % k == 0 else "." for c in range(n + 1))# 숫자 줄: 0, k, 2k, ... 를 차례로 보며 쓸 수 있는 것만 뒤에 붙인다labels = ""count = 0for m in range(0, n + 1, k): t = str(m) fits = m + len(t) - 1 <= n # 마지막 칸이 n을 넘지 않는다 gap = labels == "" or m > len(labels) # 앞 숫자와 빈칸이 하나 이상 있다 if fits and gap: labels += " " * (m - len(labels)) + t count += 1print(marks)print(labels)print(count)
JavaScriptmain.js · 19 줄
const [n, k] = require("fs").readFileSync(0, "utf8").trim().split(/\s+/).map(Number);// 눈금 줄: 칸 0 ~ n, 모두 n + 1글자let marks = "";for (let c = 0; c <= n; c++) marks += c % k === 0 ? "|" : ".";// 숫자 줄: 0, k, 2k, ... 를 차례로 보며 쓸 수 있는 것만 뒤에 붙인다let labels = "";let count = 0;for (let m = 0; m <= n; m += k) { const t = String(m); const fits = m + t.length - 1 <= n; // 마지막 칸이 n을 넘지 않는다 const gap = labels === "" || m > labels.length; // 앞 숫자와 빈칸이 하나 이상 있다 if (fits && gap) { labels += " ".repeat(m - labels.length) + t; count++; }}console.log([marks, labels, count].join("\n"));
TypeScriptmain.ts · 20 줄
import { readFileSync } from "node:fs";const [n, k]: number[] = readFileSync(0, "utf8").trim().split(/\s+/).map(Number);// 눈금 줄: 칸 0 ~ n, 모두 n + 1글자let marks = "";for (let c = 0; c <= n; c++) marks += c % k === 0 ? "|" : ".";// 숫자 줄: 0, k, 2k, ... 를 차례로 보며 쓸 수 있는 것만 뒤에 붙인다let labels = "";let count = 0;for (let m = 0; m <= n; m += k) { const t: string = String(m); const fits: boolean = m + t.length - 1 <= n; // 마지막 칸이 n을 넘지 않는다 const gap: boolean = labels === "" || m > labels.length; // 앞 숫자와 빈칸이 하나 이상 있다 if (fits && gap) { labels += " ".repeat(m - labels.length) + t; count++; }}console.log([marks, labels, String(count)].join("\n"));
JavaMain.java · 28 줄
import java.util.Scanner;public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(), k = sc.nextInt(); // 눈금 줄: 칸 0 ~ n, 모두 n + 1글자 StringBuilder marks = new StringBuilder(); for (int c = 0; c <= n; c++) marks.append(c % k == 0 ? '|' : '.'); // 숫자 줄: 0, k, 2k, ... 를 차례로 보며 쓸 수 있는 것만 뒤에 붙인다 StringBuilder labels = new StringBuilder(); int count = 0; for (int m = 0; m <= n; m += k) { String t = Integer.toString(m); boolean fits = m + t.length() - 1 <= n; // 마지막 칸이 n을 넘지 않는다 boolean gap = labels.length() == 0 || m > labels.length(); // 앞 숫자와 빈칸이 하나 이상 if (fits && gap) { labels.append(" ".repeat(m - labels.length())).append(t); count++; } } System.out.println(marks); System.out.println(labels); System.out.println(count); }}
C#Main.cs · 33 줄
using System;using System.Text;class Program{ static void Main() { string[] p = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); int n = int.Parse(p[0]), k = int.Parse(p[1]); // 눈금 줄: 칸 0 ~ n, 모두 n + 1글자 var marks = new StringBuilder(); for (int c = 0; c <= n; c++) marks.Append(c % k == 0 ? '|' : '.'); // 숫자 줄: 0, k, 2k, ... 를 차례로 보며 쓸 수 있는 것만 뒤에 붙인다 var labels = new StringBuilder(); int count = 0; for (int m = 0; m <= n; m += k) { string t = m.ToString(); bool fits = m + t.Length - 1 <= n; // 마지막 칸이 n을 넘지 않는다 bool gap = labels.Length == 0 || m > labels.Length; // 앞 숫자와 빈칸이 하나 이상 if (fits && gap) { labels.Append(' ', m - labels.Length).Append(t); count++; } } Console.WriteLine(marks); Console.WriteLine(labels); Console.WriteLine(count); }}
C++main.cpp · 26 줄
#include <iostream>#include <string>int main() { int n, k; std::cin >> n >> k; // 눈금 줄: 칸 0 ~ n, 모두 n + 1글자 std::string marks; for (int c = 0; c <= n; c++) marks += c % k == 0 ? '|' : '.'; // 숫자 줄: 0, k, 2k, ... 를 차례로 보며 쓸 수 있는 것만 뒤에 붙인다 std::string labels; int count = 0; for (int m = 0; m <= n; m += k) { std::string t = std::to_string(m); int len = static_cast<int>(labels.size()); // size()는 부호 없는 수라 int로 바꿔 비교한다 bool fits = m + static_cast<int>(t.size()) - 1 <= n; // 마지막 칸이 n을 넘지 않는다 bool gap = len == 0 || m > len; // 앞 숫자와 빈칸이 하나 이상 있다 if (fits && gap) { labels += std::string(m - len, ' ') + t; count++; } } std::cout << marks << '\n' << labels << '\n' << count << '\n';}
Cmain.c · 33 줄
#include <stdio.h>#include <string.h>#define MAXN 5000int main(void) { int n, k; scanf("%d %d", &n, &k); /* 눈금 줄: 칸 0 ~ n, 모두 n + 1글자 */ static char marks[MAXN + 2]; for (int c = 0; c <= n; c++) marks[c] = c % k == 0 ? '|' : '.'; marks[n + 1] = '\0'; /* 숫자 줄: 0, k, 2k, ... 를 차례로 보며 쓸 수 있는 것만 뒤에 붙인다 */ static char labels[MAXN + 2]; int len = 0, count = 0; char t[8]; for (int m = 0; m <= n; m += k) { int w = sprintf(t, "%d", m); /* sprintf는 쓴 글자 수를 돌려준다 */ int fits = m + w - 1 <= n; /* 마지막 칸이 n을 넘지 않는다 */ int gap = len == 0 || m > len; /* 앞 숫자와 빈칸이 하나 이상 있다 */ if (fits && gap) { while (len < m) labels[len++] = ' '; memcpy(labels + len, t, w); len += w; count++; } } labels[len] = '\0'; printf("%s\n%s\n%d\n", marks, labels, count); return 0;}
Craykonmain.cray · 35 줄
v = 콘솔.수들읽기();n = v[0];k = v[1];// 눈금 줄: 칸 0 ~ n, 모두 n + 1글자눈금 = "";반복 (c = 0; c <= n; c += 1){ 만약 (c % k == 0) { 눈금 += "|"; } 아니면 { 눈금 += "."; }}// 숫자 줄: 0, k, 2k, ... 를 차례로 보며 쓸 수 있는 것만 뒤에 붙인다숫자줄 = "";개수 = 0;반복 (m = 0; m <= n; m += k){ t = "" + m; 맞음 = m + t.길이 - 1 <= n; // 마지막 칸이 n을 넘지 않는다 띄움 = 숫자줄 == "" || m > 숫자줄.길이; // 앞 숫자와 빈칸이 하나 이상 있다 만약 (맞음 && 띄움) { 숫자줄 += " ".되풀이(m - 숫자줄.길이) + t; 개수 += 1; }}콘솔.쓰기(눈금);콘솔.쓰기(숫자줄);콘솔.쓰기(개수);