첫 줄에 단어 수 n이 주어지고, 둘째 줄에 단어 n개가 빈칸 하나씩으로 나뉘어 주어진다.
단어들을 대소문자를 무시한 순서로 정렬해 한 줄에 빈칸 하나씩 띄어 출력하라.
두 단어의 순서는 둘 다 영어 대문자를 소문자로 바꾼 다음 글자 코드(ASCII)로 정한다.
첫 글자부터 차례로 비교해 처음 다른 글자의 코드가 작은 쪽이 앞이다.
한 단어가 다른 단어의 앞부분과 같으면 짧은 쪽이 앞이다.
소문자로 바꾸면 같아지는 단어들("Bob"과 "bob")은 입력에 나온 차례를 그대로 지킨다.
글자 코드는 숫자 0~9가 48~57, 밑줄 _ 가 95, 소문자 a~z가 97~122이므로 "_x"는 "alice"보다 앞이다.
입력
1 ≤ n ≤ 2000. 단어는 1 ~ 20글자이고 영어 대문자·소문자, 숫자, 밑줄(_)로만 이루어진다
출력
정렬한 단어 n개를 빈칸 하나씩 띄어 한 줄로
예시 1 · stdin
6
bob Alice _x alice Bob x9
stdout
_x Alice alice bob Bob x9
예시 2 · stdin
4
ab a AB a_
stdout
a a_ ab AB
main.py
오류 목록00F8 ↓ · ⇧F8 ↑
입력(stdin)
실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).
$ 준비됐어요
코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.
다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이
함정이 셋이에요. 첫째, 그냥 정렬하면 대문자(65~90)가 모두 소문자(97~122)보다 앞이라 "Bob"이 "alice"보다 앞에 와요. 둘째, 대문자로 바꿔 비교하면 밑줄 _(95)이 글자 뒤로 가서 소문자로 바꿀 때와 순서가 달라요. Python key=str.upper, C# StringComparer.OrdinalIgnoreCase(문서상 대문자로 바꾼 것과 같음)가 그래요. Java compareToIgnoreCase·CASE_INSENSITIVE_ORDER는 마지막에 소문자로 비교해서 이 문제와 맞아요. JS localeCompare는 글자 코드가 아니라 사람 언어 규칙이라 _ 자리가 다르고, 철자가 같으면 소문자를 먼저 둬서 입력 차례도 깨요. 셋째, 같은 것끼리 입력 차례를 지키려면 안정 정렬이어야 해요. Python sorted, JS·TS sort(ES2019부터), Java List.sort, C# OrderBy는 안정 정렬이에요. C# List.Sort·Array.Sort, C++ std::sort, C qsort는 안정을 약속하지 않아요. C++는 std::stable_sort를 쓰고, C는 들어온 차례를 구조체에 넣어 비교의 마지막 기준으로 써요. 리눅스(glibc)의 qsort는 대개 차례를 지켜서 그냥 통과하기도 하지만, macOS에서는 실제로 섞여요. 약속이 아니니 기대면 안 돼요. 잇기는 Python " ".join(words), JS·TS words.join(" "), Java String.join(" ", words), C# string.Join(" ", words)예요. C·C++는 첫 단어 앞에만 빈칸을 빼고 써요. 크레이콘은 words.정렬(byLower)에 -1·0·1을 돌려주는 함수를 넘기고(같은 것끼리 차례를 지킴), words.잇기(" ")로 이어요.
Pythonmain.py · 4 줄
n = int(input())words = input().split()# sorted는 안정 정렬이라, 소문자로 같은 단어끼리는 들어온 차례를 지킨다print(" ".join(sorted(words, key=str.lower)))
JavaScriptmain.js · 9 줄
const [first, second] = require("fs").readFileSync(0, "utf8").split("\n");const words = second.trim().split(" ");const byLower = (a, b) => { const x = a.toLowerCase(); const y = b.toLowerCase(); return x < y ? -1 : x > y ? 1 : 0; // < 는 글자 코드 순(localeCompare 아님)};// Array.prototype.sort는 ES2019부터 안정 정렬이다console.log(words.sort(byLower).join(" "));
TypeScriptmain.ts · 10 줄
import { readFileSync } from "node:fs";const [, second] = readFileSync(0, "utf8").split("\n");const words: string[] = second.trim().split(" ");const byLower = (a: string, b: string): number => { const x: string = a.toLowerCase(); const y: string = b.toLowerCase(); return x < y ? -1 : x > y ? 1 : 0; // < 는 글자 코드 순(localeCompare 아님)};// Array.prototype.sort는 ES2019부터 안정 정렬이다console.log(words.sort(byLower).join(" "));
JavaMain.java · 18 줄
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.Arrays;import java.util.Comparator;import java.util.List;import java.util.Locale;public class Main { public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); in.readLine(); List<String> words = Arrays.asList(in.readLine().trim().split(" ")); // List.sort(객체)는 안정 정렬(TimSort). 소문자로 바꾼 것을 글자 코드로 비교한다 words.sort(Comparator.comparing((String w) -> w.toLowerCase(Locale.ROOT))); System.out.println(String.join(" ", words)); }}
C#Main.cs · 14 줄
using System;using System.Linq;class Program{ static void Main() { Console.ReadLine(); string[] words = Console.ReadLine().Trim().Split(' '); // OrderBy는 안정 정렬. Ordinal은 글자 코드 순(문화권 규칙 없이) var sorted = words.OrderBy(w => w.ToLowerInvariant(), StringComparer.Ordinal); Console.WriteLine(string.Join(" ", sorted)); }}
C++main.cpp · 22 줄
#include <algorithm>#include <cctype>#include <iostream>#include <string>#include <vector>static std::string lower(std::string s) { for (char& c : s) c = (char)std::tolower((unsigned char)c); return s;}int main() { int n; std::cin >> n; std::vector<std::string> words(n); for (auto& w : words) std::cin >> w; // std::sort는 안정 정렬이 아니다: 같은 것끼리 차례를 지키려면 stable_sort std::stable_sort(words.begin(), words.end(), [](const std::string& a, const std::string& b) { return lower(a) < lower(b); }); for (int i = 0; i < n; i++) std::cout << (i ? " " : "") << words[i]; std::cout << '\n';}
Cmain.c · 31 줄
#include <ctype.h>#include <stdio.h>#include <stdlib.h>struct Word { char text[21]; int order; /* 들어온 차례: qsort는 안정 정렬이 아니라서 직접 비교에 넣는다 */};static int by_lower(const void *pa, const void *pb) { const struct Word *a = pa, *b = pb; const unsigned char *x = (const unsigned char *)a->text, *y = (const unsigned char *)b->text; while (*x && tolower(*x) == tolower(*y)) x++, y++; int d = tolower(*x) - tolower(*y); /* 한쪽이 끝나면 '\0'(0)이라 짧은 쪽이 앞 */ if (d != 0) return d; return a->order - b->order;}int main(void) { static struct Word w[2000]; int n; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%20s", w[i].text); w[i].order = i; } qsort(w, n, sizeof w[0], by_lower); for (int i = 0; i < n; i++) printf(i ? " %s" : "%s", w[i].text); printf("\n"); return 0;}
Craykonmain.cray · 21 줄
n = 콘솔.줄읽기().수로변환();words = 콘솔.줄읽기().나누기();// 정렬(기준함수)는 같은 것끼리 들어온 차례를 지킨다words.정렬(byLower);콘솔.쓰기(words.잇기(" "));// 소문자로 바꾼 것을 글자 코드 순으로 비교byLower(앞, 뒤){ a = 앞.소문자로변환(); b = 뒤.소문자로변환(); 만약 (a < b) { 돌려주기 -1; } 만약 (a > b) { 돌려주기 1; } 돌려주기 0;}