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