import sysfrom enum import IntEnumclass Level(IntEnum): DEBUG = 10 INFO = 20 WARNING = 30 ERROR = 40 CRITICAL = 50def parse(token): """이름이나 번호를 등급으로 바꾼다. 등급이 아니면 None.""" try: if token.isdigit(): return Level(int(token)) # 값으로 찾기: 없는 값이면 ValueError return Level[token] # 이름으로 찾기: 없는 이름이면 KeyError except (ValueError, KeyError): return Nonedef main(): lines = sys.stdin.read().split("\n") m, n = map(int, lines[0].split()) count = {lv: 0 for lv in Level} # 선언한 차례대로 돈다 bad = 0 out = [] for line in lines[1:1 + n]: token, text = line.split(" ", 1) lv = parse(token) if lv is None: bad += 1 continue count[lv] += 1 if lv >= m: # IntEnum이라 정수와 바로 견줄 수 있다 out.append(f"{lv.name} {text}") for lv in Level: out.append(f"{lv.name} {count[lv]}") out.append(f"bad {bad}") print("\n".join(out))main()
TypeScriptmain.ts · 44 行
import { readFileSync } from "node:fs";enum Level { DEBUG = 10, INFO = 20, WARNING = 30, ERROR = 40, CRITICAL = 50,}// 숫자 enum은 이름 → 값, 값 → 이름 두 방향이 한 객체에 들어 있다.// Object.keys(Level)에는 "10", "20"… 도 나오므로 수가 아닌 열쇠만 골라 이름 목록을 만든다const NAMES: string[] = Object.keys(Level).filter((k) => Number.isNaN(Number(k)));function parse(token: string): Level | undefined { if (/^[0-9]+$/.test(token)) { const code = Number(token); return Level[code] !== undefined ? code : undefined; } // Level["toString"]은 물려받은 함수라서 undefined가 아니다. 선언한 이름인지 직접 확인한다 return NAMES.includes(token) ? Level[token as keyof typeof Level] : undefined;}const lines: string[] = readFileSync(0, "utf8").split("\n");const [m, n] = lines[0].split(" ").map(Number);const count = new Map<Level, number>();let bad = 0;const out: string[] = [];for (let i = 1; i <= n; i++) { const line = lines[i]; const cut = line.indexOf(" "); const lv = parse(line.slice(0, cut)); if (lv === undefined) { bad++; continue; } count.set(lv, (count.get(lv) ?? 0) + 1); if (lv >= m) out.push(`${Level[lv]} ${line.slice(cut + 1)}`);}for (const name of NAMES) { out.push(`${name} ${count.get(Level[name as keyof typeof Level]) ?? 0}`);}out.push(`bad ${bad}`);console.log(out.join("\n"));
JavaMain.java · 62 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;public class Main { // Java 열거형은 값을 스스로 갖지 않는다. 번호는 필드로 달아 준다 enum Level { DEBUG(10), INFO(20), WARNING(30), ERROR(40), CRITICAL(50); final int code; Level(int code) { this.code = code; } static Level fromCode(int code) { for (Level lv : values()) { if (lv.code == code) return lv; } return null; } } static Level parse(String token) { if (Character.isDigit(token.charAt(0))) { return Level.fromCode(Integer.parseInt(token)); } try { return Level.valueOf(token); // 없는 이름이면 IllegalArgumentException } catch (IllegalArgumentException e) { return null; } } public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] first = br.readLine().split(" "); int m = Integer.parseInt(first[0]); int n = Integer.parseInt(first[1]); int[] count = new int[Level.values().length]; // ordinal()은 0, 1, 2…인 선언 차례다 int bad = 0; StringBuilder out = new StringBuilder(); for (int i = 0; i < n; i++) { String line = br.readLine(); int cut = line.indexOf(' '); Level lv = parse(line.substring(0, cut)); if (lv == null) { bad++; continue; } count[lv.ordinal()]++; if (lv.code >= m) { out.append(lv).append(' ').append(line.substring(cut + 1)).append('\n'); } } for (Level lv : Level.values()) { out.append(lv).append(' ').append(count[lv.ordinal()]).append('\n'); } out.append("bad ").append(bad).append('\n'); System.out.print(out); }}
C#Main.cs · 44 行
using System;using System.Collections.Generic;using System.Text;enum Level{ DEBUG = 10, INFO = 20, WARNING = 30, ERROR = 40, CRITICAL = 50,}class Program{ static void Main() { string[] first = Console.ReadLine().Split(' '); int m = int.Parse(first[0]); int n = int.Parse(first[1]); var count = new Dictionary<Level, int>(); foreach (Level lv in Enum.GetValues(typeof(Level))) count[lv] = 0; int bad = 0; var sb = new StringBuilder(); for (int i = 0; i < n; i++) { string line = Console.ReadLine(); int cut = line.IndexOf(' '); string token = line.Substring(0, cut); // TryParse는 이름과 번호를 모두 받지만 "25"처럼 선언에 없는 번호도 통과시킨다. // IsDefined로 선언한 값인지 한 번 더 확인한다 if (!Enum.TryParse(token, out Level level) || !Enum.IsDefined(typeof(Level), level)) { bad++; continue; } count[level]++; if ((int)level >= m) sb.Append(level).Append(' ').Append(line.Substring(cut + 1)).Append('\n'); } foreach (Level lv in Enum.GetValues(typeof(Level))) sb.Append(lv).Append(' ').Append(count[lv]).Append('\n'); sb.Append("bad ").Append(bad).Append('\n'); Console.Write(sb); }}
C++main.cpp · 55 行
#include <array>#include <cctype>#include <iostream>#include <string>using namespace std;enum class Level { DEBUG = 10, INFO = 20, WARNING = 30, ERROR = 40, CRITICAL = 50 };// enum class는 이름 문자열도, 모든 값을 도는 방법도 주지 않아서 표를 만든다const array<pair<Level, string>, 5> TABLE = {{ {Level::DEBUG, "DEBUG"}, {Level::INFO, "INFO"}, {Level::WARNING, "WARNING"}, {Level::ERROR, "ERROR"}, {Level::CRITICAL, "CRITICAL"},}};// 등급이면 표의 몇 번째인지, 아니면 -1int parse(const string& token) { bool number = isdigit(static_cast<unsigned char>(token[0])) != 0; for (int k = 0; k < static_cast<int>(TABLE.size()); k++) { if (number) { // enum class는 정수와 바로 견줄 수 없어서 static_cast로 바꾼다 if (stoi(token) == static_cast<int>(TABLE[k].first)) return k; } else if (token == TABLE[k].second) { return k; } } return -1;}int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int m, n; cin >> m >> n; string line; getline(cin, line); array<int, 5> count{}; int bad = 0; for (int i = 0; i < n; i++) { getline(cin, line); size_t cut = line.find(' '); int k = parse(line.substr(0, cut)); if (k < 0) { bad++; continue; } count[k]++; if (static_cast<int>(TABLE[k].first) >= m) cout << TABLE[k].second << ' ' << line.substr(cut + 1) << '\n'; } for (int k = 0; k < 5; k++) cout << TABLE[k].second << ' ' << count[k] << '\n'; cout << "bad " << bad << '\n'; return 0;}
Cmain.c · 48 行
#include <ctype.h>#include <stdio.h>#include <stdlib.h>#include <string.h>/* 값을 적지 않으면 앞의 값 + 1이 된다. 다섯 개 모두 적는다 */enum Level { DEBUG = 10, INFO = 20, WARNING = 30, ERROR = 40, CRITICAL = 50 };#define KINDS 5/* C 열거형은 이름표가 붙은 정수일 뿐이라 이름 문자열은 따로 표로 만든다 */static const enum Level LEVELS[KINDS] = { DEBUG, INFO, WARNING, ERROR, CRITICAL };static const char *NAMES[KINDS] = { "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL" };/* 등급이면 표의 몇 번째인지, 아니면 -1 */static int parse(const char *token) { for (int k = 0; k < KINDS; k++) { if (isdigit((unsigned char)token[0])) { if (atoi(token) == (int)LEVELS[k]) return k; } else if (strcmp(token, NAMES[k]) == 0) { return k; } } return -1;}int main(void) { char line[128]; int m, n; if (!fgets(line, sizeof line, stdin) || sscanf(line, "%d %d", &m, &n) != 2) return 0; int count[KINDS] = { 0 }; int bad = 0; for (int i = 0; i < n; i++) { if (!fgets(line, sizeof line, stdin)) return 0; line[strcspn(line, "\n")] = '\0'; char *cut = strchr(line, ' '); *cut = '\0'; int k = parse(line); if (k < 0) { bad++; continue; } count[k]++; if ((int)LEVELS[k] >= m) printf("%s %s\n", NAMES[k], cut + 1); } for (int k = 0; k < KINDS; k++) printf("%s %d\n", NAMES[k], count[k]); printf("bad %d\n", bad); return 0;}