첫 줄에 예외 낱말 수 k가 주어지고, 둘째 줄에 예외 낱말 k개가 빈칸 하나씩으로 나뉘어 주어진다(k가 0이면 빈 줄이다).
셋째 줄에 제목 수 n이 주어지고, 이어서 영어 제목이 한 줄에 하나씩 n개 주어진다.
제목마다 제목 표기(타이틀 케이스)로 고쳐 한 줄에 하나씩 출력하라.
제목 줄은 빈칸으로 낱말을 나눈다. 줄 앞뒤의 빈칸은 버리고, 낱말 사이의 빈칸은 몇 칸이든 하나로 줄인다.
낱말 끝에 : 가 붙어 있으면 그 뒤부터 부제다. : 도 그 낱말의 일부라서 "of:"는 예외 낱말 "of"와 같지 않다.
낱말마다 먼저 영어 대문자를 모두 소문자로 바꾼다.
그 낱말이 예외 낱말 중 하나와 같고, 첫 낱말도, 마지막 낱말도, : 로 끝나는 낱말 바로 다음 낱말(부제의 첫 낱말)도 아니면 모두 소문자인 채로 둔다.
그 밖의 낱말은 맨 앞 한 글자만 대문자로 바꾼다. 맨 앞이 숫자이면 그대로 둔다.
' 나 - 뒤의 글자는 새 낱말의 시작이 아니므로 소문자로 둔다("don't" → "Don't", "e-mail" → "E-mail", "3D" → "3d").
고친 낱말들을 빈칸 하나씩으로 이어 출력한다.
입력
0 ≤ k ≤ 16, 예외 낱말은 서로 다르고 영어 소문자 1 ~ 10글자다. 1 ≤ n ≤ 100. 제목 줄은 길이 1 ~ 200이고 영어 대문자·소문자, 숫자, ' , -, :, 빈칸으로만 이루어지며 낱말이 적어도 하나 있다. 낱말은 영어 글자나 숫자로 시작하고, : 는 낱말의 맨 끝에만 올 수 있다
출력
고친 제목 n줄
예시 1 · stdin
5
a of the and in
4
the lord OF the rings
war and peace
don't look 3d e-mail
the
stdout
The Lord of the Rings
War and Peace
Don't Look 3d E-mail
The
예시 2 · stdin
2
of the
3
OF THE
THE END OF THE WORLD
the hobbit: the desolation of smaug
stdout
Of The
The End of the World
The Hobbit: The Desolation of Smaug
main.py
오류 목록00F8 ↓ · ⇧F8 ↑
입력(stdin)
실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).
$ 준비됐어요
코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.
다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이
함정이 다섯이에요. 첫째, Python str.title()은 글자가 아닌 것 바로 뒤를 모두 새 낱말로 봐서 "Don'T", "E-Mail", "3D"를 만들어요. 낱말마다 low[0].upper() + low[1:]처럼 첫 글자만 바꿔야 해요(capitalize()도 이렇게 해요). 대문자·소문자 바꾸기는 JS·TS toUpperCase·toLowerCase, Java toUpperCase(Locale.ROOT), C# ToUpperInvariant·char.ToUpperInvariant, C·C++ 글자마다 toupper·tolower, 크레이콘 대문자로변환()·소문자로변환()이에요. 둘째, 예외 낱말인지는 소문자로 바꾼 뒤에 물어야 "OF"도 잡혀요. 셋째, 첫 낱말뿐 아니라 마지막 낱말도 예외에서 빠져요. "OF THE"는 "Of The"예요. 넷째, : 뒤의 부제 첫 낱말도 예외에서 빠져요. "the hobbit: the desolation"의 둘째 "the"는 "The"예요. 앞 낱말이 :로 끝나는지는 Python endswith(":"), JS·TS·Java endsWith(":"), C# EndsWith(':'), C w[strlen(w) - 1] == ':', C++ w.back() == ':', 크레이콘 끝나나(":")로 물어요. 다섯째, 공백 다듬기와 나누기예요. Python 인자 없는 split(), C# Split(' ', StringSplitOptions.RemoveEmptyEntries), C strtok, C++ >>, 크레이콘 기준 없는 나누기()는 앞뒤·여러 칸 빈칸을 모두 건너뛰어요. JS·TS·Java의 split(" ")은 빈칸 두 개 사이와 앞쪽에 빈 문자열을 남겨서, trim() 뒤에 정규식 / +/·" +"로 나눠야 해요. 잇기는 Python " ".join(out), JS·TS out.join(" "), Java String.join(" ", words), C# string.Join(" ", words), 크레이콘 out.잇기(" ")이고, C·C++는 첫 낱말 앞만 빼고 빈칸을 써요.
Pythonmain.py · 14 줄
k = int(input())small = set(input().split())n = int(input())for _ in range(n): words = input().split() # 인자 없는 split()은 앞뒤·여러 칸 공백을 모두 없앤다 out = [] for i, w in enumerate(words): low = w.lower() # 첫 낱말, 마지막 낱말, : 뒤의 부제 첫 낱말은 예외 낱말이어도 대문자로 시작한다 if 0 < i < len(words) - 1 and not words[i - 1].endswith(":") and low in small: out.append(low) else: out.append(low[0].upper() + low[1:]) # title()은 ' 와 - 뒤도 대문자로 만든다 print(" ".join(out))
JavaScriptmain.js · 17 줄
const lines = require("fs").readFileSync(0, "utf8").split("\n");const k = Number(lines[0]);const small = new Set(lines[1].split(" ").filter((w) => w !== ""));const n = Number(lines[2]);const out = [];for (const line of lines.slice(3, 3 + n)) { // trim 뒤에 공백 덩어리로 나눈다: split(" ")은 빈 칸마다 빈 문자열을 남긴다 const words = line.trim().split(/ +/); const fixed = words.map((w, i) => { const low = w.toLowerCase(); // 첫 낱말, 마지막 낱말, : 뒤의 부제 첫 낱말은 예외 낱말이어도 대문자로 시작한다 if (i > 0 && i < words.length - 1 && !words[i - 1].endsWith(":") && small.has(low)) return low; return low[0].toUpperCase() + low.slice(1); }); out.push(fixed.join(" "));}console.log(out.join("\n"));
TypeScriptmain.ts · 18 줄
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const k: number = Number(lines[0]);const small = new Set<string>(lines[1].split(" ").filter((w) => w !== ""));const n: number = Number(lines[2]);const out: string[] = [];for (const line of lines.slice(3, 3 + n)) { // trim 뒤에 공백 덩어리로 나눈다: split(" ")은 빈 칸마다 빈 문자열을 남긴다 const words: string[] = line.trim().split(/ +/); const fixed: string[] = words.map((w: string, i: number): string => { const low: string = w.toLowerCase(); // 첫 낱말, 마지막 낱말, : 뒤의 부제 첫 낱말은 예외 낱말이어도 대문자로 시작한다 if (i > 0 && i < words.length - 1 && !words[i - 1].endsWith(":") && small.has(low)) return low; return low[0].toUpperCase() + low.slice(1); }); out.push(fixed.join(" "));}console.log(out.join("\n"));
JavaMain.java · 30 줄
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.Arrays;import java.util.HashSet;import java.util.Locale;import java.util.Set;public class Main { public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); in.readLine(); Set<String> small = new HashSet<>(Arrays.asList(in.readLine().trim().split(" "))); int n = Integer.parseInt(in.readLine().trim()); StringBuilder out = new StringBuilder(); for (int t = 0; t < n; t++) { // trim 뒤 정규식 " +"로 나눈다: split(" ")은 빈칸 두 개 사이에 빈 문자열을 남긴다 String[] words = in.readLine().trim().split(" +"); for (int i = 0; i < words.length; i++) { String low = words[i].toLowerCase(Locale.ROOT); // 첫 낱말, 마지막 낱말, : 뒤의 부제 첫 낱말은 예외 낱말이어도 대문자로 시작한다 boolean inner = i > 0 && i < words.length - 1 && !words[i - 1].endsWith(":"); if (inner && small.contains(low)) words[i] = low; else words[i] = low.substring(0, 1).toUpperCase(Locale.ROOT) + low.substring(1); } out.append(String.join(" ", words)).append('\n'); } System.out.print(out); }}
C#Main.cs · 26 줄
using System;using System.Collections.Generic;class Program{ static void Main() { Console.ReadLine(); var small = new HashSet<string>(Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries)); int n = int.Parse(Console.ReadLine()); for (int t = 0; t < n; t++) { // RemoveEmptyEntries가 앞뒤·여러 칸 공백에서 생기는 빈 조각을 버린다 string[] words = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < words.Length; i++) { string low = words[i].ToLowerInvariant(); // 첫 낱말, 마지막 낱말, : 뒤의 부제 첫 낱말은 예외 낱말이어도 대문자로 시작한다 bool inner = i > 0 && i < words.Length - 1 && !words[i - 1].EndsWith(':'); if (inner && small.Contains(low)) words[i] = low; else words[i] = char.ToUpperInvariant(low[0]) + low.Substring(1); } Console.WriteLine(string.Join(" ", words)); } }}
C++main.cpp · 35 줄
#include <cctype>#include <iostream>#include <sstream>#include <string>#include <unordered_set>#include <vector>int main() { int k, n; std::cin >> k; std::unordered_set<std::string> small; for (int i = 0; i < k; i++) { std::string w; std::cin >> w; small.insert(w); } std::cin >> n; std::string line; std::getline(std::cin, line); // n 뒤의 줄 끝 for (int t = 0; t < n && std::getline(std::cin, line); t++) { // >> 는 앞뒤·여러 칸 빈칸을 건너뛰고 낱말만 읽는다 std::istringstream ss(line); std::vector<std::string> words; for (std::string w; ss >> w;) words.push_back(w); for (size_t i = 0; i < words.size(); i++) { std::string& w = words[i]; for (char& c : w) c = (char)std::tolower((unsigned char)c); // 첫 낱말, 마지막 낱말, : 뒤의 부제 첫 낱말은 예외 낱말이어도 대문자로 시작한다 bool inner = i > 0 && i + 1 < words.size() && words[i - 1].back() != ':'; if (!(inner && small.count(w))) w[0] = (char)std::toupper((unsigned char)w[0]); std::cout << (i ? " " : "") << w; } std::cout << '\n'; }}
Cmain.c · 39 줄
#include <stdio.h>#include <string.h>#include <ctype.h>static char small[20][16];static int k;static int isSmall(const char *w) { for (int i = 0; i < k; i++) if (strcmp(small[i], w) == 0) return 1; return 0;}int main(void) { int n; char line[256]; scanf("%d", &k); for (int i = 0; i < k; i++) scanf("%15s", small[i]); scanf("%d", &n); fgets(line, sizeof line, stdin); /* n 뒤의 줄 끝 */ for (int t = 0; t < n; t++) { if (!fgets(line, sizeof line, stdin)) break; line[strcspn(line, "\n")] = '\0'; /* strtok은 앞뒤·여러 칸 빈칸을 건너뛰고 낱말만 준다 */ char *words[128]; int m = 0; for (char *w = strtok(line, " "); w; w = strtok(NULL, " ")) words[m++] = w; for (int i = 0; i < m; i++) { for (char *p = words[i]; *p; p++) *p = (char)tolower((unsigned char)*p); /* 첫 낱말, 마지막 낱말, : 뒤의 부제 첫 낱말은 예외 낱말이어도 대문자로 시작한다 */ int inner = i > 0 && i < m - 1 && words[i - 1][strlen(words[i - 1]) - 1] != ':'; if (!(inner && isSmall(words[i]))) words[i][0] = (char)toupper((unsigned char)words[i][0]); printf(i == 0 ? "%s" : " %s", words[i]); } putchar('\n'); } return 0;}
Craykonmain.cray · 27 줄
k = 콘솔.줄읽기().수로변환();small = 사전();각각 (w 에서 콘솔.줄읽기().나누기()){ small[w] = 참;}n = 콘솔.줄읽기().수로변환();반복 (t = 0; t < n; t++){ // 기준 없는 나누기()는 앞뒤·여러 칸 빈칸을 모두 건너뛴다 words = 콘솔.줄읽기().공백제거().나누기(); out = []; 반복 (i = 0; i < words.개수; i++) { low = words[i].소문자로변환(); // 첫 낱말, 마지막 낱말, : 뒤의 부제 첫 낱말은 예외 낱말이어도 대문자로 시작한다 만약 (i > 0 && i < words.개수 - 1 && !words[i - 1].끝나나(":") && small.있나(low)) { out.넣기(low); } 아니면 { out.넣기(low[0].대문자로변환() + low.부분문자열(1)); } } 콘솔.쓰기(out.잇기(" "));}