{ }codelper
열거형여러 갈래 조건세기P0198

주사위 다섯 개의 족보

주사위 놀이에서 사람마다 주사위 다섯 개(눈은 1 ~ 6)를 한 번 던진다. 던진 다섯 눈의 족보는 다음 여덟 족보 가운데 들어맞는 것 중 가장 위에 있는 것이다.
위에 있을수록 센 족보다. - FIVE: 다섯 개가 모두 같은 눈 - FOUR: 네 개가 같은 눈 - FULLHOUSE: 세 개가 같은 눈이고 나머지 두 개가 그와 다른 같은 눈 - STRAIGHT: 다섯 눈이 1 2 3 4 5 또는 2 3 4 5 6(차례는 상관없다) - TRIPLE: 세 개가 같은 눈이고 나머지 두 개는 그 눈과도 서로도 다르다 - TWOPAIR: 서로 다른 두 눈이 두 개씩 있다 - PAIR: 두 개가 같은 눈인 것이 한 쌍뿐이다 - NOTHING: 그 밖의 모든 경우 첫 줄에 사람 수 n, 다음 n줄에 줄마다 한 사람이 던진 다섯 눈이 빈칸으로 나뉘어 주어진다.
사람 번호는 1부터 차례로 붙는다. 사람마다 족보 이름을 한 줄에 하나씩 대문자로 출력하라. 마지막 줄에는 이긴 사람의 번호를 출력하라. 족보가 가장 센 사람이 이기고, 족보가 같으면 다섯 눈의 합이 큰 사람이 이긴다.
그것도 같으면 번호가 작은 사람이 이긴다. 족보를 약한 것부터 센 것까지 여덟 값을 가진 열거형(enum)으로 만들고, 족보끼리는 열거형 값의 크기로 비교해 보자.

입력
1 ≤ n ≤ 1,000, 주사위 눈은 1 ~ 6의 정수
출력
n+1줄: 사람마다 족보 이름, 마지막 줄에 이긴 사람의 번호
예시 1 · stdin
5
3 3 3 5 5
2 4 3 6 5
6 2 6 2 3
5 5 3 3 3
1 2 3 4 6
stdout
FULLHOUSE
STRAIGHT
TWOPAIR
FULLHOUSE
NOTHING
1
main.py
입력(stdin)

실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).

$ 준비됐어요

코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.

다른 언어로는?언어별 풀이 보기 · 6개 언어 풀이

이 문제는 열거형이 있는 Python·TypeScript·Java·C#·C·C++만 받아요.
JavaScript에는 열거형 문법이 없고 크레이콘에도 없어요.
족보를 약한 것부터 선언하면 값의 크기가 곧 세기라서 "더 센가"를 > 하나로 물을 수 있는데, 열거형을 크기로 비교하는 법이 언어마다 달라요.
Python 그냥 Enum은 <·>를 몰라서 TypeError가 나요.
IntEnum으로 만들거나 .value로 비교해요.
TypeScript 숫자 enum과 C# enum은 >로 바로 비교되고, C++ enum class도 같은 타입끼리는 <·>가 돼요(정수와 섞을 때만 static_cast가 필요해요).
Java enum은 >를 못 쓰고, 선언 차례(ordinal())로 비교하는 compareTo를 써요.
C enum은 이름 붙은 int 상수라서 그냥 >로 비교돼요.
이름 찍기도 달라요: Python h.name, TS 역방향 표 Hand[h], Java toString(), C# ToString().ToUpperInvariant()(선언한 FullHouse를 대문자로), C는 이름표 배열, C++은 switch로 이름을 돌려줘요.
함정 다섯: ① Python IntEnum 값을 그대로 print(h)하면 3.11부터 이름이 아니라 5 같은 수가 나와요(그냥 Enum은 Hand.FULLHOUSE).
② 그냥 Enum에 >를 쓰면 실행하다 TypeError로 멈춰요.
③ 센 족보부터 물어야 해요.
"셋이 같은가"를 풀하우스보다 먼저 물으면 3 3 3 5 5가 TRIPLE이 돼요.
④ "가장 큰 눈 - 가장 작은 눈 == 4"만으로는 스트레이트가 아니에요.
1 1 1 3 5도 그렇거든요.
다섯 눈이 모두 달라야 해요(그러면 빠진 눈이 1이나 6일 때만 이어져요).
⑤ 족보와 합이 같으면 앞 사람이 이기니, 바꿀 때는 >만 쓰고 >=는 안 돼요.
그리고 열거형을 센 것부터 선언했다면(FIVE가 0) 비교 방향도 뒤집어야 해요.

Pythonmain.py · 48 줄
import sysfrom collections import Counterfrom enum import IntEnum  class Hand(IntEnum):    # 약한 것부터 적어서 값이 클수록 센 족보가 된다(IntEnum이라 > 로 비교할 수 있다)    NOTHING = 0    PAIR = 1    TWOPAIR = 2    TRIPLE = 3    STRAIGHT = 4    FULLHOUSE = 5    FOUR = 6    FIVE = 7  def classify(dice):    counts = sorted(Counter(dice).values(), reverse=True)  # 같은 눈이 몇 개씩인가, 많은 것부터    if counts[0] == 5:        return Hand.FIVE    if counts[0] == 4:        return Hand.FOUR    if counts == [3, 2]:        return Hand.FULLHOUSE    if sorted(dice) in ([1, 2, 3, 4, 5], [2, 3, 4, 5, 6]):        return Hand.STRAIGHT    if counts[0] == 3:        return Hand.TRIPLE    if counts == [2, 2, 1]:        return Hand.TWOPAIR    if counts[0] == 2:        return Hand.PAIR    return Hand.NOTHING  lines = sys.stdin.read().split("\n")n = int(lines[0])best = None  # (족보, 합, 번호)out = []for i in range(1, n + 1):    dice = list(map(int, lines[i].split()))    h = classify(dice)    out.append(h.name)  # print(h)는 IntEnum이라 "7"처럼 수가 나온다    if best is None or (h, sum(dice)) > (best[0], best[1]):        best = (h, sum(dice), i)out.append(str(best[2]))print("\n".join(out))
TypeScriptmain.ts · 48 줄
import { readFileSync } from "node:fs"; // 약한 것부터 적으면 값(0, 1, 2…)이 클수록 센 족보가 된다enum Hand {  NOTHING,  PAIR,  TWOPAIR,  TRIPLE,  STRAIGHT,  FULLHOUSE,  FOUR,  FIVE,} function classify(dice: number[]): Hand {  const cnt: number[] = new Array<number>(7).fill(0); // cnt[눈] = 그 눈이 나온 주사위 수  for (const d of dice) cnt[d]++;  const most = Math.max(...cnt);  const pairs = cnt.filter((c) => c === 2).length;  const triple = cnt.includes(3);  if (most === 5) return Hand.FIVE;  if (most === 4) return Hand.FOUR;  if (triple && pairs === 1) return Hand.FULLHOUSE;  // 다섯 눈이 모두 다르면 빠진 눈은 하나: 1이나 6이 빠졌을 때만 이어진다  if (most === 1 && (cnt[1] === 0 || cnt[6] === 0)) return Hand.STRAIGHT;  if (triple) return Hand.TRIPLE;  if (pairs === 2) return Hand.TWOPAIR;  if (pairs === 1) return Hand.PAIR;  return Hand.NOTHING;} const lines: string[] = readFileSync(0, "utf8").split("\n");const n = Number(lines[0]);const out: string[] = [];let bestHand = Hand.NOTHING, bestSum = -1, winner = 0;for (let i = 1; i <= n; i++) {  const dice = lines[i].trim().split(/\s+/).map(Number);  const h = classify(dice);  const sum = dice.reduce((a, b) => a + b, 0);  out.push(Hand[h]); // h는 수라서 이름은 역방향 표 Hand[h]로 꺼낸다  if (h > bestHand || (h === bestHand && sum > bestSum)) {    bestHand = h;    bestSum = sum;    winner = i;  }}out.push(String(winner));console.log(out.join("\n"));
JavaMain.java · 55 줄
import java.io.*;import java.util.*; public class Main {    // 약한 것부터 적으면 선언 차례(ordinal)가 곧 세기 차례다    enum Hand { NOTHING, PAIR, TWOPAIR, TRIPLE, STRAIGHT, FULLHOUSE, FOUR, FIVE }     static Hand classify(int[] dice) {        int[] cnt = new int[7]; // cnt[눈] = 그 눈이 나온 주사위 수        for (int d : dice) cnt[d]++;        int most = 0, pairs = 0;        boolean triple = false;        for (int c : cnt) {            most = Math.max(most, c);            if (c == 2) pairs++;            if (c == 3) triple = true;        }        if (most == 5) return Hand.FIVE;        if (most == 4) return Hand.FOUR;        if (triple && pairs == 1) return Hand.FULLHOUSE;        // 다섯 눈이 모두 다르면 빠진 눈은 하나: 1이나 6이 빠졌을 때만 이어진다        if (most == 1 && (cnt[1] == 0 || cnt[6] == 0)) return Hand.STRAIGHT;        if (triple) return Hand.TRIPLE;        if (pairs == 2) return Hand.TWOPAIR;        if (pairs == 1) return Hand.PAIR;        return Hand.NOTHING;    }     public static void main(String[] args) throws IOException {        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));        int n = Integer.parseInt(br.readLine().trim());        StringBuilder sb = new StringBuilder();        Hand bestHand = null;        int bestSum = -1, winner = 0;        for (int i = 1; i <= n; i++) {            StringTokenizer st = new StringTokenizer(br.readLine());            int[] dice = new int[5];            int sum = 0;            for (int k = 0; k < 5; k++) {                dice[k] = Integer.parseInt(st.nextToken());                sum += dice[k];            }            Hand h = classify(dice);            sb.append(h).append('\n'); // enum의 toString()은 이름            // enum의 compareTo는 선언 차례로 비교한다            if (bestHand == null || h.compareTo(bestHand) > 0 || (h == bestHand && sum > bestSum)) {                bestHand = h;                bestSum = sum;                winner = i;            }        }        sb.append(winner).append('\n');        System.out.print(sb);    }}
C#Main.cs · 50 줄
using System;using System.Linq;using System.Text; // 약한 것부터 적으면 값(0, 1, 2…)이 클수록 센 족보가 된다enum Hand { Nothing, Pair, TwoPair, Triple, Straight, FullHouse, Four, Five } class Program{    static Hand Classify(int[] dice)    {        var cnt = new int[7]; // cnt[눈] = 그 눈이 나온 주사위 수        foreach (int d in dice) cnt[d]++;        int most = cnt.Max();        int pairs = cnt.Count(c => c == 2);        bool triple = cnt.Contains(3);        if (most == 5) return Hand.Five;        if (most == 4) return Hand.Four;        if (triple && pairs == 1) return Hand.FullHouse;        // 다섯 눈이 모두 다르면 빠진 눈은 하나: 1이나 6이 빠졌을 때만 이어진다        if (most == 1 && (cnt[1] == 0 || cnt[6] == 0)) return Hand.Straight;        if (triple) return Hand.Triple;        if (pairs == 2) return Hand.TwoPair;        if (pairs == 1) return Hand.Pair;        return Hand.Nothing;    }     static void Main()    {        int n = int.Parse(Console.ReadLine()!.Trim());        var sb = new StringBuilder();        Hand bestHand = Hand.Nothing;        int bestSum = -1, winner = 0;        for (int i = 1; i <= n; i++)        {            int[] dice = Console.ReadLine()!.Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();            Hand h = Classify(dice);            int sum = dice.Sum();            sb.Append(h.ToString().ToUpperInvariant()).Append('\n'); // ToString()은 "FullHouse"            if (h > bestHand || (h == bestHand && sum > bestSum))            {                bestHand = h;                bestSum = sum;                winner = i;            }        }        sb.Append(winner).Append('\n');        Console.Write(sb);    }}
C++main.cpp · 63 줄
#include <algorithm>#include <array>#include <iostream>#include <string> // 약한 것부터 적으면 선언 차례가 곧 세기 차례다. enum class끼리는 < > 로 바로 비교된다enum class Hand { Nothing, Pair, TwoPair, Triple, Straight, FullHouse, Four, Five }; // enum class는 자기 이름을 모르니 switch로 돌려준다std::string name(Hand h) {    switch (h) {        case Hand::Nothing: return "NOTHING";        case Hand::Pair: return "PAIR";        case Hand::TwoPair: return "TWOPAIR";        case Hand::Triple: return "TRIPLE";        case Hand::Straight: return "STRAIGHT";        case Hand::FullHouse: return "FULLHOUSE";        case Hand::Four: return "FOUR";        case Hand::Five: return "FIVE";    }    return "";} Hand classify(const std::array<int, 5>& dice) {    std::array<int, 7> cnt{}; // cnt[눈] = 그 눈이 나온 주사위 수    for (int d : dice) cnt[d]++;    int most = *std::max_element(cnt.begin(), cnt.end());    int pairs = std::count(cnt.begin(), cnt.end(), 2);    bool triple = std::count(cnt.begin(), cnt.end(), 3) > 0;    if (most == 5) return Hand::Five;    if (most == 4) return Hand::Four;    if (triple && pairs == 1) return Hand::FullHouse;    // 다섯 눈이 모두 다르면 빠진 눈은 하나: 1이나 6이 빠졌을 때만 이어진다    if (most == 1 && (cnt[1] == 0 || cnt[6] == 0)) return Hand::Straight;    if (triple) return Hand::Triple;    if (pairs == 2) return Hand::TwoPair;    if (pairs == 1) return Hand::Pair;    return Hand::Nothing;} int main() {    std::ios::sync_with_stdio(false);    int n;    std::cin >> n;    Hand bestHand = Hand::Nothing;    int bestSum = -1, winner = 0;    for (int i = 1; i <= n; i++) {        std::array<int, 5> dice;        int sum = 0;        for (int& d : dice) {            std::cin >> d;            sum += d;        }        Hand h = classify(dice);        std::cout << name(h) << "\n";        if (h > bestHand || (h == bestHand && sum > bestSum)) {            bestHand = h;            bestSum = sum;            winner = i;        }    }    std::cout << winner << "\n";}
Cmain.c · 51 줄
#include <stdbool.h>#include <stdio.h> // 약한 것부터 적으면 값(0, 1, 2…)이 클수록 센 족보가 된다enum Hand { NOTHING, PAIR, TWOPAIR, TRIPLE, STRAIGHT, FULLHOUSE, FOUR, FIVE };// C의 enum은 이름을 모르는 int 상수라서 이름표를 따로 둔다(차례를 enum과 똑같이)static const char *NAME[] = {"NOTHING", "PAIR", "TWOPAIR", "TRIPLE", "STRAIGHT", "FULLHOUSE", "FOUR", "FIVE"}; enum Hand classify(const int dice[5]) {    int cnt[7] = {0}; // cnt[눈] = 그 눈이 나온 주사위 수    for (int k = 0; k < 5; k++) cnt[dice[k]]++;    int most = 0, pairs = 0;    bool triple = false;    for (int v = 1; v <= 6; v++) {        if (cnt[v] > most) most = cnt[v];        if (cnt[v] == 2) pairs++;        if (cnt[v] == 3) triple = true;    }    if (most == 5) return FIVE;    if (most == 4) return FOUR;    if (triple && pairs == 1) return FULLHOUSE;    // 다섯 눈이 모두 다르면 빠진 눈은 하나: 1이나 6이 빠졌을 때만 이어진다    if (most == 1 && (cnt[1] == 0 || cnt[6] == 0)) return STRAIGHT;    if (triple) return TRIPLE;    if (pairs == 2) return TWOPAIR;    if (pairs == 1) return PAIR;    return NOTHING;} int main(void) {    int n;    scanf("%d", &n);    enum Hand best_hand = NOTHING;    int best_sum = -1, winner = 0;    for (int i = 1; i <= n; i++) {        int dice[5], sum = 0;        for (int k = 0; k < 5; k++) {            scanf("%d", &dice[k]);            sum += dice[k];        }        enum Hand h = classify(dice);        puts(NAME[h]);        if (h > best_hand || (h == best_hand && sum > best_sum)) {            best_hand = h;            best_sum = sum;            winner = i;        }    }    printf("%d\n", winner);    return 0;}