import sysdef page_parts(pages): """정렬되고 겹치지 않는 쪽 번호를 '3', '5-7' 같은 조각으로 바꾼다.""" parts = [] i = 0 while i < len(pages): j = i while j + 1 < len(pages) and pages[j + 1] == pages[j] + 1: j += 1 if j - i >= 2: # 셋 이상 이어질 때만 범위로 줄인다 parts.append(f"{pages[i]}-{pages[j]}") else: parts.extend(str(p) for p in pages[i : j + 1]) i = j + 1 return partsdef main(): data = sys.stdin.read().split() n = int(data[0]) index = {} for i in range(n): word, page = data[1 + 2 * i], int(data[2 + 2 * i]) index.setdefault(word, set()).add(page) # 집합이라 같은 쪽은 한 번만 남는다 lines = [] for word in sorted(index): parts = page_parts(sorted(index[word])) lines.append(word + ": " + ", ".join(parts)) # join은 '사이'에만 넣는다 print("\n".join(lines))main()
JavaScriptmain.js · 36 行
const data = require("fs").readFileSync(0, "utf8").split(/\s+/).filter((s) => s !== "");const n = Number(data[0]);// 낱말 → 쪽 번호 집합(Set이라 같은 쪽은 한 번만 남는다)const index = new Map();for (let i = 0; i < n; i++) { const word = data[1 + 2 * i]; const page = Number(data[2 + 2 * i]); if (!index.has(word)) index.set(word, new Set()); index.get(word).add(page);}// 정렬되고 겹치지 않는 쪽 번호를 "3", "5-7" 같은 조각으로 바꾼다function pageParts(pages) { const parts = []; let i = 0; while (i < pages.length) { let j = i; while (j + 1 < pages.length && pages[j + 1] === pages[j] + 1) j++; if (j - i >= 2) { parts.push(`${pages[i]}-${pages[j]}`); // 셋 이상 이어질 때만 범위로 줄인다 } else { for (let t = i; t <= j; t++) parts.push(String(pages[t])); } i = j + 1; } return parts;}const lines = [];for (const word of [...index.keys()].sort()) { // 수는 비교 함수를 줘야 크기 순이 된다(그냥 sort()는 문자열로 바꿔 견준다) const pages = [...index.get(word)].sort((a, b) => a - b); lines.push(word + ": " + pageParts(pages).join(", "));}console.log(lines.join("\n"));
TypeScriptmain.ts · 42 行
import { readFileSync } from "node:fs";const data: string[] = readFileSync(0, "utf8").split(/\s+/).filter((s) => s !== "");const n = Number(data[0]);// 낱말 → 쪽 번호 집합(Set이라 같은 쪽은 한 번만 남는다)const index = new Map<string, Set<number>>();for (let i = 0; i < n; i++) { const word = data[1 + 2 * i]; const page = Number(data[2 + 2 * i]); let pages = index.get(word); if (pages === undefined) { pages = new Set<number>(); index.set(word, pages); } pages.add(page);}// 정렬되고 겹치지 않는 쪽 번호를 "3", "5-7" 같은 조각으로 바꾼다function pageParts(pages: number[]): string[] { const parts: string[] = []; let i = 0; while (i < pages.length) { let j = i; while (j + 1 < pages.length && pages[j + 1] === pages[j] + 1) j++; if (j - i >= 2) { parts.push(`${pages[i]}-${pages[j]}`); // 셋 이상 이어질 때만 범위로 줄인다 } else { for (let t = i; t <= j; t++) parts.push(String(pages[t])); } i = j + 1; } return parts;}const lines: string[] = [];for (const [word, set] of [...index.entries()].sort((a, b) => (a[0] < b[0] ? -1 : 1))) { // 수는 비교 함수를 줘야 크기 순이 된다(그냥 sort()는 문자열로 바꿔 견준다) const pages = [...set].sort((a, b) => a - b); lines.push(word + ": " + pageParts(pages).join(", "));}console.log(lines.join("\n"));
JavaMain.java · 50 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.List;import java.util.Map;import java.util.StringTokenizer;import java.util.TreeMap;import java.util.TreeSet;public class Main { // 정렬되고 겹치지 않는 쪽 번호를 "3", "5-7" 같은 조각으로 바꾼다 static List<String> pageParts(List<Integer> pages) { List<String> parts = new ArrayList<>(); int i = 0; while (i < pages.size()) { int j = i; while (j + 1 < pages.size() && pages.get(j + 1) == pages.get(j) + 1) j++; if (j - i >= 2) { parts.add(pages.get(i) + "-" + pages.get(j)); // 셋 이상 이어질 때만 범위로 줄인다 } else { for (int t = i; t <= j; t++) parts.add(String.valueOf(pages.get(t))); } i = j + 1; } return parts; } public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine().trim()); // TreeMap·TreeSet은 넣기만 해도 정렬되고, 집합이라 같은 쪽은 한 번만 남는다 TreeMap<String, TreeSet<Integer>> index = new TreeMap<>(); for (int i = 0; i < n; i++) { StringTokenizer st = new StringTokenizer(br.readLine()); String word = st.nextToken(); int page = Integer.parseInt(st.nextToken()); index.computeIfAbsent(word, k -> new TreeSet<>()).add(page); } StringBuilder sb = new StringBuilder(); for (Map.Entry<String, TreeSet<Integer>> e : index.entrySet()) { List<String> parts = pageParts(new ArrayList<>(e.getValue())); // String.join은 문자열만 받는다(수는 먼저 문자열로 바꿔 둔다) sb.append(e.getKey()).append(": ").append(String.join(", ", parts)).append('\n'); } System.out.print(sb); }}
C#Main.cs · 54 行
using System;using System.Collections.Generic;using System.Text;class Program{ // 정렬되고 겹치지 않는 쪽 번호를 "3", "5-7" 같은 조각으로 바꾼다 static List<string> PageParts(List<int> pages) { var parts = new List<string>(); int i = 0; while (i < pages.Count) { int j = i; while (j + 1 < pages.Count && pages[j + 1] == pages[j] + 1) j++; if (j - i >= 2) { parts.Add($"{pages[i]}-{pages[j]}"); // 셋 이상 이어질 때만 범위로 줄인다 } else { for (int t = i; t <= j; t++) parts.Add(pages[t].ToString()); } i = j + 1; } return parts; } static void Main() { int n = int.Parse(Console.ReadLine()); // SortedDictionary·SortedSet은 넣기만 해도 정렬되고, 집합이라 같은 쪽은 한 번만 남는다 var index = new SortedDictionary<string, SortedSet<int>>(StringComparer.Ordinal); for (int i = 0; i < n; i++) { string[] t = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); if (!index.TryGetValue(t[0], out var pages)) { pages = new SortedSet<int>(); index[t[0]] = pages; } pages.Add(int.Parse(t[1])); } var sb = new StringBuilder(); foreach (var e in index) { List<string> parts = PageParts(new List<int>(e.Value)); sb.Append(e.Key).Append(": ").Append(string.Join(", ", parts)).Append('\n'); } Console.Write(sb); }}
C++main.cpp · 51 行
#include <iostream>#include <map>#include <set>#include <string>#include <vector>using namespace std;// 정렬되고 겹치지 않는 쪽 번호를 "3", "5-7" 같은 조각으로 바꾼다vector<string> pageParts(const vector<int>& pages) { vector<string> parts; size_t i = 0; while (i < pages.size()) { size_t j = i; while (j + 1 < pages.size() && pages[j + 1] == pages[j] + 1) j++; if (j - i >= 2) { parts.push_back(to_string(pages[i]) + "-" + to_string(pages[j])); // 셋 이상만 범위로 } else { for (size_t t = i; t <= j; t++) parts.push_back(to_string(pages[t])); } i = j + 1; } return parts;}int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; // map·set은 넣기만 해도 정렬되고, set이라 같은 쪽은 한 번만 남는다 map<string, set<int>> index; for (int i = 0; i < n; i++) { string word; int page; cin >> word >> page; index[word].insert(page); } for (const auto& [word, pageSet] : index) { vector<string> parts = pageParts(vector<int>(pageSet.begin(), pageSet.end())); // std::string에는 join이 없으니 '첫 조각이 아니면 앞에 쉼표'로 잇는다 string line = word + ": "; for (size_t t = 0; t < parts.size(); t++) { if (t > 0) line += ", "; line += parts[t]; } cout << line << '\n'; } return 0;}
Cmain.c · 62 行
#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct { char word[11]; int page;} Entry;// 낱말 순, 같은 낱말이면 쪽 번호 순static int cmp(const void *a, const void *b) { const Entry *x = a, *y = b; int c = strcmp(x->word, y->word); if (c != 0) return c; return (x->page > y->page) - (x->page < y->page);}int main(void) { int n; if (scanf("%d", &n) != 1) return 1; Entry *e = malloc(sizeof(Entry) * n); for (int i = 0; i < n; i++) scanf("%10s %d", e[i].word, &e[i].page); // C에는 사전이 없으니 정렬해서 같은 낱말을 한데 모은다 qsort(e, n, sizeof(Entry), cmp); int *pages = malloc(sizeof(int) * n); int i = 0; while (i < n) { // 같은 낱말의 쪽 번호를 겹치지 않게 모은다 int cnt = 0, k = i; while (k < n && strcmp(e[k].word, e[i].word) == 0) { if (cnt == 0 || pages[cnt - 1] != e[k].page) pages[cnt++] = e[k].page; k++; } printf("%s: ", e[i].word); // join이 없으니 '첫 조각이 아니면 앞에 쉼표'로 사이에만 넣는다 int first = 1; int a = 0; while (a < cnt) { int b = a; while (b + 1 < cnt && pages[b + 1] == pages[b] + 1) b++; if (b - a >= 2) { // 셋 이상 이어질 때만 범위로 줄인다 printf(first ? "%d-%d" : ", %d-%d", pages[a], pages[b]); first = 0; } else { for (int t = a; t <= b; t++) { printf(first ? "%d" : ", %d", pages[t]); first = 0; } } a = b + 1; } printf("\n"); i = k; } free(pages); free(e); return 0;}
Craykonmain.cray · 55 行
n = コンソール.行読み().空白除去().数に();// 낱말 → 쪽 번호 목록index = 辞書();繰り返す (i = 0; i < n; i++){ t = コンソール.行読み().空白除去().分ける(); もし (!index.含む(t[0])) { index[t[0]] = []; } index[t[0]].追加(t[1].数に()); // 수로 바꿔 넣어야 크기 순으로 정렬된다}words = index.キー一覧;words.並べ替え();それぞれ (word の中 words){ all = index[word]; all.並べ替え(); // 같은 쪽은 한 번만 남긴다(정렬했으니 바로 앞과만 견주면 된다) pages = []; それぞれ (p の中 all) { もし (pages.個数 == 0 || pages[pages.個数 - 1] != p) { pages.追加(p); } } parts = []; i = 0; 間 (i < pages.個数) { j = i; 間 (j + 1 < pages.個数 && pages[j + 1] == pages[j] + 1) { j++; } もし (j - i >= 2) { parts.追加(pages[i] + "-" + pages[j]); // 셋 이상 이어질 때만 범위로 줄인다 } でなければ { 繰り返す (k = i; k <= j; k++) { parts.追加(pages[k]); } } i = j + 1; } コンソール.書く(word + ": " + parts.つなぐ(", ")); // 잇기는 '사이'에만 넣는다}