계산대에서 상품 n개의 코드를 하나씩 찍었다.
첫 줄에 n이, 둘째 줄에 찍은 차례대로 코드 n개가 빈칸으로 띄워 주어진다.
코드는 영어 소문자와 숫자로 된 1~8글자 문자열이다.
코드는 문자열 그대로 비교한다. 그래서 "007"과 "7"은 다른 코드다.
서로 다른 코드마다 한 줄에 코드와 찍힌 횟수를 빈칸 하나로 띄워 출력하라.
줄의 차례는 그 코드가 처음 찍힌 차례다.
입력
1 ≤ n ≤ 5,000, 코드는 영어 소문자(a~z)와 숫자(0~9)로 된 1~8글자
출력
서로 다른 코드마다 한 줄(코드, 횟수), 처음 찍힌 차례대로
예시 1 · stdin
6
milk 42 egg 7 42 milk
stdout
milk 2
42 2
egg 1
7 1
예시 2 · stdin
4
007 7 07 7
stdout
007 1
7 2
07 1
main.py
오류 목록00F8 ↓ · ⇧F8 ↑
입력(stdin)
실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).
$ 준비됐어요
코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.
다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이
개수 세기는 사전 하나면 돼요. Python counts[c] = counts.get(c, 0) + 1, JS·TS Map의 set(c, (get(c) ?? 0) + 1), Java merge(c, 1, Integer::sum), C# TryGetValue, C++ counts[c]++(없는 열쇠는 0으로 생겨요), 크레이콘 사전()과 있나예요. 이 문제의 함정은 돌 때의 차례예요. Python dict(3.7부터), JS·TS Map, Java LinkedHashMap, 크레이콘 사전의 열쇠목록은 처음 넣은 차례를 지켜요. Java HashMap과 C++ unordered_map은 차례가 뒤섞이고, C++ std::map은 열쇠의 사전 순으로 돌아요. C# Dictionary는 지우지 않으면 넣은 차례로 도는 것처럼 보이지만 문서가 약속하지 않으니, 처음 나온 코드를 목록에 따로 적어 두는 게 안전해요. JS 객체 {}도 함정이에요. "42"처럼 앞에 0이 없는 0 이상의 정수로 읽히는 열쇠는 넣은 차례와 상관없이 작은 수부터 맨 앞에 와요("007"은 그렇지 않아요). 또 JS·TS에서 늘 쓰던 .split(/\s+/).map(Number)로 읽으면 "007"은 7이 되고 글자 코드는 모두 NaN이 되니, 코드는 문자열 그대로 둬요. C에는 사전이 없어서 처음 나온 차례대로 배열에 적고 strcmp로 앞에서부터 찾아요.
Pythonmain.py · 7 줄
n = int(input())counts = {}for code in input().split(): counts[code] = counts.get(code, 0) + 1# dict는 처음 넣은 차례를 지킨다(3.7부터 언어 규칙)for code, c in counts.items(): print(code, c)
JavaScriptmain.js · 9 줄
const [n, ...codes] = require("fs").readFileSync(0, "utf8").trim().split(/\s+/);// Map은 처음 넣은 차례를 지킨다. 객체 {}는 "42" 같은 숫자 열쇠를 앞으로 당긴다const counts = new Map();for (const code of codes) { counts.set(code, (counts.get(code) ?? 0) + 1);}const out = [];for (const [code, c] of counts) out.push(`${code} ${c}`);console.log(out.join("\n"));
TypeScriptmain.ts · 9 줄
import { readFileSync } from "node:fs";const [n, ...codes]: string[] = readFileSync(0, "utf8").trim().split(/\s+/);const counts = new Map<string, number>();for (const code of codes) { counts.set(code, (counts.get(code) ?? 0) + 1);}const out: string[] = [];for (const [code, c] of counts) out.push(`${code} ${c}`);console.log(out.join("\n"));
JavaMain.java · 21 줄
import java.io.BufferedReader;import java.io.InputStreamReader;import java.util.LinkedHashMap;import java.util.Map;public class Main { public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); br.readLine(); // HashMap은 차례가 뒤섞인다. LinkedHashMap이 넣은 차례를 지킨다 Map<String, Integer> counts = new LinkedHashMap<>(); for (String code : br.readLine().trim().split("\\s+")) { counts.merge(code, 1, Integer::sum); } StringBuilder out = new StringBuilder(); for (Map.Entry<String, Integer> e : counts.entrySet()) { out.append(e.getKey()).append(' ').append(e.getValue()).append('\n'); } System.out.print(out); }}
C#Main.cs · 29 줄
using System;using System.Collections.Generic;using System.Text;class Program{ static void Main() { Console.ReadLine(); // Dictionary의 차례는 문서가 약속하지 않으니, 처음 나온 차례를 목록에 따로 적는다 var counts = new Dictionary<string, int>(); var order = new List<string>(); foreach (string code in Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries)) { if (counts.TryGetValue(code, out int c)) { counts[code] = c + 1; } else { counts[code] = 1; order.Add(code); } } var sb = new StringBuilder(); foreach (string code in order) sb.Append(code).Append(' ').Append(counts[code]).Append('\n'); Console.Write(sb); }}
C++main.cpp · 19 줄
#include <iostream>#include <string>#include <unordered_map>#include <vector>int main() { std::ios::sync_with_stdio(false); int n; std::cin >> n; // std::map은 열쇠 순으로, unordered_map은 뒤섞인 차례로 돈다. 처음 나온 차례는 따로 적는다 std::unordered_map<std::string, int> counts; std::vector<std::string> order; for (int i = 0; i < n; i++) { std::string code; std::cin >> code; if (counts[code]++ == 0) order.push_back(code); } for (const std::string& code : order) std::cout << code << " " << counts[code] << "\n";}
Cmain.c · 25 줄
#include <stdio.h>#include <string.h>/* C에는 사전이 없어서, 처음 나온 차례대로 코드와 개수를 배열에 적고 찾을 때는 앞에서부터 훑는다 */static char names[5000][9];static int counts[5000];int main(void) { int n, kinds = 0; char code[16]; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%15s", code); int j = 0; while (j < kinds && strcmp(names[j], code) != 0) j++; if (j == kinds) { strcpy(names[kinds], code); counts[kinds] = 0; kinds++; } counts[j]++; } for (int j = 0; j < kinds; j++) printf("%s %d\n", names[j], counts[j]); return 0;}
Craykonmain.cray · 16 줄
n = 콘솔.줄읽기().수로변환();codes = 콘솔.줄읽기().공백제거().나누기(" ");counts = 사전();각각 (code 에서 codes){ 만약 (!counts.있나(code)) { counts[code] = 0; } counts[code] = counts[code] + 1;}// 크레이콘 사전의 열쇠목록은 처음 넣은 차례다각각 (code 에서 counts.열쇠목록){ 콘솔.쓰기(code + " " + counts[code]);}