ポーカーの役判定
お題にしようと思っていたのに間違えてしまいました。今から変更可能でしょうか?
(説明) 当初間違ってトピックに投稿していたので、このようなコメントを付けていたのですが、 このコメントに気づいた管理人さんにお題に移していただきました。 (最初の2つだけ投稿日時が早いのはそのためです)
Posted feedbacks - Nested
Flatten Hidden素直に順番に条件チェックしてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Sample121 {
private static final String RANK_LIST = "A23456789TJQKA";
private static final String ROYAL = "royal ";
private static final String STRAIGHT = "straight";
private static final String FLUSH = "flush";
private static final String FULL_HOUSE = "Full house";
private static final String CARDS_4 = "Four of a kind";
private static final String CARDS_3 = "Three of a kind";
private static final String PAIR_2 = "Two pair";
private static final String PAIR_1 = "One pair";
private static final String Nothing = "No pair";
public static String getPokerRole(String cards) {
if (cards.length() != 2 * 5) throw new IllegalArgumentException();
String rankList = createRankList(cards);
boolean flush = isFlush(cards);
boolean straight = isStraight(rankList);
if (flush || straight) {
boolean royal = isRoyal(rankList);
if (royal) {
return format(flush? ROYAL + FLUSH: ROYAL + STRAIGHT);
} else {
if (flush && straight) {
return format(STRAIGHT + " " + FLUSH);
} else {
return format(flush? FLUSH: STRAIGHT);
}
}
}
Integer[] integers = countSameNumber(rankList);
switch (integers[0]) {
case 4:
return CARDS_4;
case 3:
if (integers[1] == 2) {
return FULL_HOUSE;
} else {
return CARDS_3;
}
case 2:
if (integers[1] == 2) {
return PAIR_2;
} else {
return PAIR_1;
}
}
return Nothing;
}
private static String format(String str) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
private static boolean isFlush(String cards) {
char suit = cards.charAt(0);
for (int index = 1; index < 5; index++) {
if (suit != cards.charAt(index * 2)) {
return false;
}
}
return true;
}
private static String createRankList(String cards) {
StringBuilder builder = new StringBuilder();
for (int index = 0; index < 5; index++) {
final char rank = cards.charAt(index * 2 + 1);
int insert = 0;
for (; insert < builder.length(); insert++) {
if (RANK_LIST.indexOf(builder.charAt(insert)) > RANK_LIST.indexOf(rank)) {
break;
}
}
builder.insert(insert, rank);
}
return builder.toString();
}
private static boolean isStraight(String rankList) {
return RANK_LIST.indexOf(rankList) >= 0;
}
private static boolean isRoyal(String rankList) {
return rankList.equals("ATJQK");
}
private static Integer[] countSameNumber(String rankList) {
Map<Character, Integer> map = new HashMap<Character, Integer>();
for (int index = 0; index < rankList.length(); index++) {
char c = rankList.charAt(index);
Integer integer = map.get(c);
if (integer == null) {
integer = 1;
map.put(c, integer);
} else {
map.put(c, integer + 1);
}
}
List<Integer> result = new ArrayList<Integer>(map.values());
Collections.sort(result, Collections.reverseOrder());
return result.toArray(new Integer[0]);
}
public static void main(String[] args) {
System.out.println(getPokerRole("SQSJSASKST"));
System.out.println(getPokerRole("D9D7D6D5D8"));
System.out.println(getPokerRole("C2D2S2H3H2"));
System.out.println(getPokerRole("C2D3S2H3H2"));
System.out.println(getPokerRole("S9S4S8STSJ"));
System.out.println(getPokerRole("C4H7D5S6H3"));
System.out.println(getPokerRole("S6H6C5DQC6"));
System.out.println(getPokerRole("S6HQC5DQC6"));
System.out.println(getPokerRole("S6H4C5DQC6"));
System.out.println(getPokerRole("SJSQSKSAC2"));
}
}
|
こんな感じ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | import sys
import collections
def solve(s):
it = iter(s)
cards = []
for _ in xrange(5):
suit = "SDHC".index(it.next())
number = "A23456789TJQK".index(it.next()) + 1
cards.append((suit, number))
counts = collections.defaultdict(int)
for suit, number in cards:
counts[number] += 1
counts = sorted(counts.itervalues())
flush = all(cards[0][0] == suit for suit, number in cards[1:])
numbers = sorted(number for suit, number in cards)
royal_straight = (numbers == [1, 10, 11, 12, 13])
straight = all(numbers[i] + 1 == numbers[i + 1] for i in xrange(4)) or royal_straight
if royal_straight and flush:
return "Royal flush"
elif straight and flush:
return "Straight flush"
elif counts == [1, 4]:
return "Four of a kind"
elif counts == [2, 3]:
return "Full House"
elif flush:
return "Flush"
elif straight:
return "Straight"
elif counts == [1, 1, 3]:
return "Three of a kind"
elif counts == [1, 2, 2]:
return "Two pair"
elif counts == [1, 1, 1, 2]:
return "One pair"
else:
assert counts == [1, 1, 1, 1, 1]
return "No pair"
def main():
if len(sys.argv) >= 2:
for s in sys.argv[1:]:
print solve(s)
else:
print solve("SQSJSASKST") # Royal flush
print solve("D9D7D6D5D8") # Straight flush
print solve("C2D2S2H3H2") # Four of a kind
print solve("C2D3S2H3H2") # Full house
print solve("S9S4S8STSJ") # Flush
print solve("C4H7D5S6H3") # Straight
print solve("S6H6C5DQC6") # Three of a kind
print solve("S6HQC5DQC6") # Two pair
print solve("S6H4C5DQC6") # One pair
print solve("SJSQSKSAC2") # No pair
if __name__ == '__main__':
main()
|
パターンマッチって素晴らしい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | object Poker {
def whatHand_?(_cs:String) = {
val rank = Map((0 to 12).map(i => "A23456789TJQK"(i) -> (i+1)).toArray:_*)
val cs = (0.until(_cs.size, 2)).map(_cs.substring).
map{s=>(s(0), rank(s(1)))}.toList.sort(_._2<_._2)
val royalSt_? = cs match{
case List((_,1),(_,10),(_,11),(_,12),(_,13)) => true
case _ => false
}
val flush_? = cs.forall(cs(0)._1 == _._1)
val st_? = (1 to 9).map(i=>cs(0)._2==i && cs(4)._2==i+4).exists(true==) || royalSt_?
val p = (((List(List[(char,int)]())) /: List.make(2, cs)){
for(i <-_; j <-_) yield j::i
}.filter(c=>c(0)._2 == c(1)._2).size - 5)/2
(royalSt_?, flush_?, st_?, p) match {
case (true, true, _, _) => "Royal flush"
case (_, true, true,_) => "Straight flush"
case (_, true, _ ,_) => "Flush"
case (_, _, true ,_) => "Straight"
case (_,_,_, 6) => "Four of a kind"
case (_,_,_, 4) => "Full house"
case (_,_,_, 3) => "Three of a kind"
case (_,_,_, 2) => "Two pairs"
case (_,_,_, 1) => "One pair"
case _ => "No pair"
}
}
}
|
すみません、1箇所ミスってました。
1 2 3 4 5 6 7 8 9 | @@ -8,7 +8,7 @@
case _ => false
}
val flush_? = cs.forall(cs(0)._1 == _._1)
- val st_? = (1 to 9).map(i=>cs(0)._2==i && cs(4)._2==i+4).exists(true==) || royalSt_?
+ val st_? = (1 to 9).map(i=>(0 to 4).forall(j=>cs(j)._2==i+j)).exists(true==) || royalSt_?
val p = (((List(List[(char,int)]())) /: List.make(2, cs)){
for(i <-_; j <-_) yield j::i
}.filter(c=>c(0)._2 == c(1)._2).size - 5)/2
|
ペア判定以外の上手な判定方法が思いつきませんでした。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | #include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
// パラメータのチェック(不十分)
if ( argc != 2 )
{
cout << "fatal arguments" << endl << "exp) ./poker SQSJSASKST" << endl;
return -1;
}
// 手札を配列に直す
int a[5];
char suit = argv[1][0];
bool flush_flag = true;
for(char i = 0; i < 5; i++)
{
char num = argv[1][i*2+1];
if ( num == 'A' )
a[i] = 1;
else if ( num == 'T' )
a[i] = 10;
else if ( num == 'J' )
a[i] = 11;
else if ( num == 'Q' )
a[i] = 12;
else if ( num == 'K' )
a[i] = 13;
else
a[i] = num - '0';
// フラッシュをついでに計算
if ( suit != argv[1][i*2] )
flush_flag = false;
}
// ペアを計算
int count = 0;
for(int y=0; y<5; y++)
for(int x=y; x<5; x++)
if ( x != y && a[x] == a[y] )
count ++;
// ストレートを計算
bool straight_flag = true;
bool royal_straight_flag = true;
// sort
for(int y=0; y<5; y++)
for(int x=5; x>=y+1; x--)
if ( a[x] < a[x-1] )
{
int t = a[x];
a[x] = a[x-1];
a[x-1] = t;
}
if ( a[4] == 13 )
{
straight_flag = false;
for(int i=1; i<5; i++)
royal_straight_flag &= (a[i] == i + 9);
royal_straight_flag &= (suit == 'S');
}
else
{
royal_straight_flag = false;
for(int i=0; i<5; i++)
straight_flag &= (a[i] == i + a[0]);
}
straight_flag |= royal_straight_flag;
// 役の表示
if ( straight_flag )
{
if ( royal_straight_flag && flush_flag )
{
cout << "Royal flush" << endl; // Royal Straight Flush ??
}
else if ( flush_flag )
{
cout << "Straight flush" << endl;
}
else
{
cout << "Straight" << endl;
}
}
else if ( flush_flag )
{
cout << "Flush" << endl;
}
else
{
switch ( count )
{
case 1:
cout << "One pair" << endl;
break;
case 2:
cout << "Two pair" << endl;
break;
case 3:
cout << "Three of a kind" << endl;
break;
case 4:
cout << "Full house" << endl;
break;
case 6:
cout << "Four of a kind" << endl;
break;
default:
cout << "No pair" << endl;
}
}
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | //http://ja.doukaku.org/121/ 投稿用
using System;
using System.Collections.Generic;
class Program {
const string Ranks = "A23456789TJQKA";
const string Suits = "SDHC";
static void Main(string[] args) {
if(IsRoyalStraightFlush(args[0])) Console.WriteLine("Royal straight flush");
else if(IsStraightFlush(args[0])) Console.WriteLine("Straight flush");
else if(Is4cards(args[0])) Console.WriteLine("Four of a kind");
else if(IsFullHouse(args[0])) Console.WriteLine("Full house");
else if(IsFlush(args[0])) Console.WriteLine("Flush");
else if(IsStraight(args[0])) Console.WriteLine("Straight");
else if(Is3Cards(args[0])) Console.WriteLine("Three of a kind");
else if(Is2Pair(args[0])) Console.WriteLine("Two pair");
else if(Is1Pair(args[0])) Console.WriteLine("One pair");
else Console.WriteLine("No pair");
Console.ReadLine();
}
static bool IsRoyalStraightFlush(string cards){
if(IsFlush(cards) && IsStraight(cards)){
for(int i = 2; i <= 9; i++) {//2~9までの数字が含まれていたらNG
if(cards.IndexOf(i.ToString()) != -1) return false;
}
return true;
}
return false;
}
static bool IsStraightFlush(string cards) {
return IsFlush(cards) && IsStraight(cards);
}
static bool Is4cards(string cards) {
return IsAnyCards(cards, 4);
}
static bool IsFullHouse(string cards) {
return Is3Cards(cards) && Is1Pair(cards);
}
static bool IsFlush(string cards) {
foreach(char suit in Suits.ToCharArray()) {//あるスーツの文字を切り取って
if(cards.Length - cards.Replace(suit.ToString(),"").Length == 5) return true;
//5文字減ったら5枚全て同じスーツ
}
return false;
}
static bool IsStraight(string cards) {
List<string> rankListInCards = new List<string>();//カードのランクのみ
//ランク切り出し
for(int i = 1; i <= 9; i = i + 2) {
rankListInCards.Add(cards[i].ToString());
}
//並び替え
rankListInCards.Sort(cardRankSort);
//ソート済みカードリスト作成
string sortedCards = "";
foreach(string card in rankListInCards) {
sortedCards += card;
}
//判定
if(Ranks.Contains(sortedCards)) return true;
if(sortedCards[0] == 'A') {//先頭がAなら
//末尾に移してもう一度判定
if(Ranks.Contains(sortedCards.Remove(0, 1).PadRight(5, 'A'))) return true;
}
return false;
}
static bool Is3Cards(string cards) {
return IsAnyCards(cards, 3);
}
static bool Is2Pair(string cards) {
foreach(char Rank in Ranks.ToCharArray()) {
if(cards.Length - cards.Replace(Rank.ToString(), "").Length == 2) {//One pairだったら
return Is1Pair(cards.Replace(Rank.ToString(),""));//One pairが2回でTwo pair
}
}
return false;
}
static bool Is1Pair(string cards) {
return IsAnyCards(cards, 2);
}
//あるカードがany枚含まれているかどうかを判定
static bool IsAnyCards(string cards, int any) {
foreach(char Rank in Ranks.ToCharArray()) {
if(cards.Length - cards.Replace(Rank.ToString(), "").Length == any) return true;
}
return false;
}
static int cardRankSort(string x, string y) {
return Ranks.IndexOf(x) - Ranks.IndexOf(y);
}
}
|
思ったより時間かかってしまいました
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | using System;
namespace Poker
{
class Program
{
static void Main(string[] args)
{
if (args.Length != 1)
return;
Poker poker = new Poker(args[0]);
Console.WriteLine(poker.Judge());
}
}
public class Poker
{
static string RANK = "A23456789TJQK";
string cards;
string ranks;
public Poker(string card)
{
cards = card;
ranks = SortRanks();
}
public string Judge()
{
bool isRoyalStraight = ranks == "ATJQK";
bool isStraight = RANK.IndexOf(ranks) >= 0;
bool isFlush = IsFlush();
string sameRanks = GetSameRanks();
if (isRoyalStraight && isFlush)
return "Royal flush";
else if (isStraight && isFlush)
return "Straight flush";
else if (isStraight)
return "Straight";
else if (isFlush)
return "Flush";
else if (sameRanks == "4")
return "Four of a kind";
else if (sameRanks == "23")
return "Full house";
else if (sameRanks == "3")
return "Three of a kind";
else if (sameRanks == "22")
return "Two pair";
else if(sameRanks == "2")
return "One pair";
else
return "No pair";
}
private string GetSameRanks()
{
int[] rankArray = new int[13];
string sameRanks = "";
for (int i = 0; i < rankArray.Length; i++)
rankArray[i] = 0;
for (int i = 0; i < ranks.Length; i++) {
switch (ranks[i]) {
case 'A':
rankArray[0]++;
break;
case 'T':
rankArray[9]++;
break;
case 'J':
rankArray[10]++;
break;
case 'Q':
rankArray[11]++;
break;
case 'K':
rankArray[12]++;
break;
default:
rankArray[ranks[i] - 48 - 1]++;
break;
}
}
Array.Sort(rankArray);
foreach (int n in rankArray) {
if (n > 1)
sameRanks += n.ToString();
}
return sameRanks;
}
private bool IsFlush()
{
char suit = cards[0];
for (int i = 2; i < cards.Length; i += 2) {
if (cards[i] != suit)
return false;
}
return true;
}
private string SortRanks()
{
char[] rankBuff = new char[5];
string sortedRank = "";
for (int i = 0; i < rankBuff.Length; i++)
rankBuff[i] = cards[i * 2 + 1];
for (int i = 0; i < RANK.Length; i++) {
char c = RANK[i];
foreach (char c2 in rankBuff) {
if (c == c2)
sortedRank += c.ToString();
}
}
return sortedRank;
}
}
}
|
GetSameRanks()で文字列のフラグを生成する発想は無かったです。
文字列のチェックは最低限ですが 役判定も短めにまとめてみました☆
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | #include<stdio.h>
#include<string.h>
void fortune(char *cards){
char *ranklist = "A23456789TJQK";
int suit[5], rank[5], straight = 0, flush = 0, pair = 0, i, j;
for(i = 0; i < 5; i++)
suit[i] = cards[i * 2],
rank[i] = strchr(ranklist, cards[i * 2 + 1]) - ranklist,
straight |= 1 << rank[i];
while(straight % 2 < 1)
straight /= 2;
for(i = 0; i < 4; i++)
for(j = i + 1; j < 5; j++)
flush += (suit[i] == suit[j]),
pair += (rank[i] == rank[j]);
if(flush == 10 && straight == 7681) printf("Royal flush\n");
else if(flush == 10 && straight == 31) printf("Straight flush\n");
else if(pair == 6) printf("Four of a kind\n");
else if(pair == 4) printf("Full house\n");
else if(flush == 10) printf("Flush\n");
else if(straight == 7681 || straight == 31) printf("Straight\n");
else if(pair == 3) printf("Three of a kind\n");
else if(pair == 2) printf("Two pair\n");
else if(pair == 1) printf("One pair\n");
else printf("No pair\n");
}
int main(void){
fortune("SQSJSASKST");
fortune("D9D7D6D5D8");
fortune("C2D2S2H3H2");
fortune("C2D3S2H3H2");
fortune("S9S4S8STSJ");
fortune("C4H7D5S6H3");
fortune("S6H6C5DQC6");
fortune("S6HQC5DQC6");
fortune("S6H4C5DQC6");
fortune("SJSQSKSAC2");
fortune("SQSJDASKST");
fortune("S4S3DASKS2");
return 0;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | //http://ja.doukaku.org/121/ 投稿用
using System;
using System.Collections.Generic;
class Program {
const string Ranks = "A23456789TJQKA";
const string Suits = "SDHC";
enum Hands {
Five_of_a_kind = 10,
Royal_straight_flush = 9,
Straight_flush = 8,
Four_of_a_kind = 7,
Full_house = 6,
Flush = 5,
Straight = 4,
Three_of_a_kind = 3,
Two_pair = 2,
One_pair = 1,
No_pair = 0
}
static void Main(string[] args) {
Hands hand = 0;
foreach(char suit in Suits.ToCharArray()) {
foreach(char rank in Ranks.Remove(0, 1).ToCharArray()) {
string wildCard = suit.ToString() + rank.ToString();
Hands tmpHand = GetHands(args[0].Replace("WW", wildCard));
hand = tmpHand > hand ? tmpHand : hand;
}
}
Console.WriteLine(hand);
Console.ReadLine();
}
static Hands GetHands(string cards) {
if(Is5cards(cards)) return Hands.Five_of_a_kind;
else if(IsRoyalStraightFlush(cards)) return Hands.Royal_straight_flush;
else if(IsStraightFlush(cards)) return Hands.Straight_flush;
else if(Is4cards(cards)) return Hands.Five_of_a_kind;
else if(IsFullHouse(cards)) return Hands.Full_house;
else if(IsFlush(cards)) return Hands.Flush;
else if(IsStraight(cards)) return Hands.Straight;
else if(Is3Cards(cards)) return Hands.Three_of_a_kind;
else if(Is2Pair(cards)) return Hands.Two_pair;
else if(Is1Pair(cards)) return Hands.One_pair;
return Hands.No_pair;
}
static bool Is5cards(string cards) {
return IsAnyCards(cards, 5);
}
static bool IsRoyalStraightFlush(string cards){
if(IsFlush(cards) && IsStraight(cards)){
for(int i = 2; i <= 9; i++) {//2~9までの数字が含まれていたらNG
if(cards.IndexOf(i.ToString()) != -1) return false;
}
return true;
}
return false;
}
static bool IsStraightFlush(string cards) {
return IsFlush(cards) && IsStraight(cards);
}
static bool Is4cards(string cards) {
return IsAnyCards(cards, 4);
}
static bool IsFullHouse(string cards) {
return Is3Cards(cards) && Is1Pair(cards);
}
static bool IsFlush(string cards) {
foreach(char suit in Suits.ToCharArray()) {//あるスーツの文字を切り取って
if(cards.Length - cards.Replace(suit.ToString(),"").Length == 5) return true;
//5文字減ったら5枚全て同じスーツ
}
return false;
}
static bool IsStraight(string cards) {
List<string> rankListInCards = new List<string>();//カードのランクのみ
//ランク切り出し
for(int i = 1; i <= 9; i = i + 2) {
rankListInCards.Add(cards[i].ToString());
}
//並び替え
rankListInCards.Sort(cardRankSort);
//ソート済みカードリスト作成
string sortedCards = "";
foreach(string card in rankListInCards) {
sortedCards += card;
}
//判定
if(Ranks.Contains(sortedCards)) return true;
if(sortedCards[0] == 'A') {//先頭がAなら
//末尾に移してもう一度判定
if(Ranks.Contains(sortedCards.Remove(0, 1).PadRight(5, 'A'))) return true;
}
return false;
}
static bool Is3Cards(string cards) {
return IsAnyCards(cards, 3);
}
static bool Is2Pair(string cards) {
foreach(char Rank in Ranks.ToCharArray()) {
if(cards.Length - cards.Replace(Rank.ToString(), "").Length == 2) {//One pairだったら
return Is1Pair(cards.Replace(Rank.ToString(),""));//One pairが2回でTwo pair
}
}
return false;
}
static bool Is1Pair(string cards) {
return IsAnyCards(cards, 2);
}
//あるカードがany枚含まれているかどうかを判定
static bool IsAnyCards(string cards, int any) {
foreach(char Rank in Ranks.ToCharArray()) {
if(cards.Length - cards.Replace(Rank.ToString(), "").Length == any) return true;
}
return false;
}
static int cardRankSort(string x, string y) {
return Ranks.IndexOf(x) - Ranks.IndexOf(y);
}
}
|
実行結果:
(format t "~A => ~A~%" x (hand x "SQSJSASKST"))
;==>
;SQSJSASKST => Royal straight flash
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | (defpackage :doukaku-121 (:use :cl :ppcre))
(in-package :doukaku-121)
(defun break-part (str &optional (ace-val 1) &aux suit rank)
(do-matches-as-strings (match "([SDHC][A2-9TJQK])" str)
(push (schar match 0) suit)
(push (schar match 1) rank))
(values
(sublis `((A . ,ace-val) (T . 10) (J . 11) (Q . 12) (K . 13))
(mapcar (lambda (x)(read-from-string (string x)))
(nreverse rank)))
suit))
(defun flashp (str)
(let ((s (nth-value 1 (break-part str))))
(and (every (lambda (x) (char= (car s) x)) s) 'flash)))
(defun kinds (str)
(let ((k (length (delete-duplicates (break-part str)))))
(if (= k 5) nil k)))
(defun straightp (str)
(flet ((check (str ace)
(let ((lst (sort (break-part str ace) #'<)))
(mapc (lambda (x y) (unless (= 1 (- y x)) (return-from check nil)))
lst (cdr lst))
(values 'straight (if (= 1 ace) nil 'royal)))))
(or (check str 1) (check str 14))))
(defun 3-2p (str)
(do ((l (break-part str) (cdr l)))
((null (cddr l)) nil)
(case (count (car l) l)
(3 (return t))
(4 (return nil)))))
(defun hand (str &optional (out t))
(multiple-value-bind (straightp royalp) (straightp str)
(let ((hand (list royalp straightp (flashp str) (kinds str) (3-2p str))))
(destructuring-bind (ignore flashp kinds 3-2p) hand
(declare (ignore ignore))
(if 3-2p
(case kinds
(2 (format out "Full house"))
(3 (format out "Three of a kind")))
(case kinds
(2 (format out "Four of a kind"))
(3 (format out "Two pair"))
(4 (format out "One paire"))
(otherwise (if (or straightp flashp)
(format out "~@(~{~@[~A ~]~}~)" hand)
(format out "No pair")))))))))
|
すいません、修正前のをコピペしてました。実行例も不要なxが混じってました。正確には、 (format t "~A => ~A~%" (hand "SQSJSASKST")) です。
1 2 3 4 | 40c40
< (destructuring-bind (ignore flashp kinds 3-2p) hand
---
> (destructuring-bind (ignore flashp straightp kinds 3-2p) hand
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Poker {
public static void main(String[] args) {
System.out.println(getPokerRole("SQSJSASKST"));
System.out.println(getPokerRole("D9D7D6D5D8"));
System.out.println(getPokerRole("C2D2S2H3H2"));
System.out.println(getPokerRole("C2D3S2H3H2"));
System.out.println(getPokerRole("S9S4S8STSJ"));
System.out.println(getPokerRole("C4H7D5S6H3"));
System.out.println(getPokerRole("S6H6C5DQC6"));
System.out.println(getPokerRole("S6HQC5DQC6"));
System.out.println(getPokerRole("S6H4C5DQC6"));
System.out.println(getPokerRole("SJSQSKSAC2"));
}
private static String getPokerRole(String aCards) {
List<int[]> tCards = new ArrayList<int[]>();
for (int i = 0; i < aCards.length(); i += 2) {
tCards.add(new int[] { aCards.charAt(i), 1 + "A23456789TJQK".indexOf(aCards.charAt(i + 1)) });
}
Collections.sort(tCards, new Comparator<int[]>() {
public int compare(int[] aLeftCard, int[] aRightCard) {
return aLeftCard[1] - aRightCard[1];
}
});
int tRoyalCardCount = 0;
boolean tIsStraight = true;
boolean tIsFlush = true;
int[] tPairs = new int[5];
int tPairKinds = 0;
for (int i = 0; i < tCards.size(); i++) {
if (Arrays.binarySearch(new int[] { 1, 10, 11, 12, 13 }, tCards.get(i)[1]) >= 0) {
tRoyalCardCount++;
}
if (i == 0) {
continue;
}
if (tCards.get(i - 1)[0] != tCards.get(i)[0]) {
tIsFlush = false;
}
if (tCards.get(i - 1)[1] + 1 != tCards.get(i)[1]) {
tIsStraight = false;
}
if (tCards.get(i - 1)[1] == tCards.get(i)[1]) {
tPairs[tPairKinds]++;
} else {
tPairKinds++;
}
}
Arrays.sort(tPairs);
if (tRoyalCardCount == 5 && tIsFlush) {
return "Royal flush";
} else if (tIsFlush && tIsStraight) {
return "Straight flush";
} else if (tIsFlush) {
return "Flush";
} else if (tIsStraight) {
return "Straight";
} else if (tPairs[4] == 3) {
return "Four of a kind";
} else if (tPairs[4] == 2 && tPairs[3] == 1) {
return "Full house";
} else if (tPairs[4] == 2) {
return "Three of a kind";
} else if (tPairs[4] == 1 && tPairs[3] == 1) {
return "Two pair";
} else if (tPairs[4] == 1 && tPairs[3] == 0) {
return "One pair";
}
return "No pair";
}
}
|
Squeak Smalltalk で。
バッグ(a Bag)はマルチセットとも呼ばれる特殊なコレクションのひとつで、要素を、その種類と出現数との組として管理しています。情報は内包される辞書に保持され、#valuesAndCounts をコールすることでアクセスできます。なお、Smalltalk で辞書(a Dictionary)とは、連想配列のことを指します。
辞書は #values で、自らが要素として持つ「キー -> 値」の組の「値」(この場合、出現数)のみを抽出した配列を返します。本スクリプトでは、この出現数のみを抽出した配列(ソート済み)のパターンを見て(#caseOf:otherwise:)、手の役(ストレートやフラッシュ以外の…)を判定しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | | 入力 ランク順 ランク スート |
入力 := 'SQSJSASKST'.
ランク順 := 'A', ($2 to: $9), 'TJQK'.
ランク := Bag new.
スート := Bag new.
入力 pairsDo: [:a :b | スート add: a. ランク add: (ランク順 indexOf: b)].
スート asSet size = 1 ifTrue: [
ランク asSortedArray = #(1 10 11 12 13) ifTrue: [^'Royal flush'].
ランク asSortedArray = (ランク min to: ランク min + 4) ifTrue: [^'Straight flush'].
^'Flush'].
ランク asSortedArray = (ランク min to: ランク min + 4) ifTrue: [^'Straight'].
^ランク valuesAndCounts values sort caseOf: {
[#(1 4)] -> ['Four of a kind'].
[#(2 3)] -> ['Full house'].
[#(1 1 3)] -> ['Three of a kind'].
[#(1 2 2)] -> ['Two pair'].
[#(1 1 1 2)] -> ['One pair']} otherwise: ['No pair']
|
面倒なので、大文字ではなくて、小文字でカードを記述しています。スマートに出来るかと思ったけど、結局力業でした。 実行結果: $ pl -qs 121.pl sqsjsaskst->Royal flush d9d7d6d5d8->Straight flush c2d2s2h3h2->four of a kind c2d3s2h3h2->Full house s9s4s8stsj->Flush c4h7d5s6h3->Straight s6h6c5dqc6->Three of a kind s6hqc5dqc6->Two pair s6h4c5dqc6->One pair sjsqsksac2->No Pair ?-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | straight([(_,A)|As]):-seq(A,As).
seq(_,[]).
seq(P,[(_,N)|Ns]):-succ(P,N),seq(N,Ns).
flush([(A,_)|As]):-flush0(A,As).
flush0(_,[]).
flush0(A,[(A,_)|As]):-flush0(A,As).
count([],[]).
count([(_,N)|Ns],R):-count(Ns,Rs),countw(N,Rs,R).
countw(N,[],[(N,1)]).
countw(N,[(N,C0)|R],[(N,C)|R]):-succ(C0,C).
countw(N,[P|R0],[P|R]):-countw(N,R0,R).
sortcard(C,Cs):-predsort(cmp,C,Cs).
cmp(>,(_,N1),(_,N2)):-N1>N2,!.
cmp(<,_,_):-!.
p([(S,1),(S,10),(S,11),(S,12),(S,13)],'Royal flush'):-!.
p(C, 'Straight flush'):-straight(C),flush(C),!.
p(C, 'Flush'):-flush(C),!.
p(C, 'Straight'):-straight(C),!.
p(C, R) :- count(C,C1), maplist(arg(2),C1,C2),msort(C2,C3),n(C3, R).
p(_, 'No Pair').
n([2,3],'Full house'):-!.
n([1,4],'four of a kind'):-!.
n([1,1,3],'Three of a kind'):-!.
n([1,2,2],'Two pair'):-!.
n([1,1,1,2],'One pair'):-!.
tcard1([],[]).
tcard1([S,Na|Cs],[(S,N)|Cs1]):-nth1(N,[a,'2','3','4','5','6','7','8','9',t,j,q,k],Na),tcard1(Cs,Cs1).
poker(C,R):-atom_chars(C,Cs),tcard1(Cs,R0),sortcard(R0,R1),p(R1,R),!.
test(C):-poker(C,R),write(C->R),nl.
:-maplist(test,[sqsjsaskst,
d9d7d6d5d8,
c2d2s2h3h2,
c2d3s2h3h2,
s9s4s8stsj,
c4h7d5s6h3,
s6h6c5dqc6,
s6hqc5dqc6,
s6h4c5dqc6,
sjsqsksac2]).
|
ああ、そうだ。このお題は良い問題だと思います。
Mac OS X (PowerPC 32bit) アセンブリで。PowerPCアセンブリ読めというのも無茶なので、以下やってることの説明です。先にほとんど同じロジック(#5168)で投稿されてしまいましたけど。
スート役は「すべてのスート役が同じ」場合のみ成り立つので、最初のスートを記録しておき、二枚目以降と比較すれば判断できます。途中に一つでも異なるスートがあれば、スート用レジスタを 0 にします。このレジスタには最初のスートのASCIIコードが入っているので、レジスタが 0 でなければフラッシュ系の役が成立することになります。
ランク役では、重複した枚数ごとにレジスタを用意します。このレジスタは1-13までのランクをビットで表したフラグです。
- r8: ノーペア(1枚)
- r9: ワンペア(2枚)
- r10: スリーカード(3枚)
- r11: フォーカード(4枚)
最初のカードのランクは、ノーペア用レジスタのビット 1<<ランク を立てます(ランクが5なら 1<<4 )。次のカードのランクも同じであれば、ワンペア用レジスタの同ビットを立てて、ノーペア用レジスタの同ビットを下ろします。これでペアは判断できます。
最後にストレートとロイヤルフラッシュですが、ノーペア用レジスタを使います。ロイヤルフラッシュはATJQKの組み合わせが決まっていますから、その箇所のビットを立てたビットマスクで判断できます。ストレートは連続した5つのビット(11111)をシフトしながらAND演算して判断します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 | ;; ------------------------------------------------
;; poker.s for Mac OS X (PowerPC 32bit)
;; % as -o poker.o poker.s && gcc poker.o -o poker
;; ------------------------------------------------
.machine ppc
.globl _main
;; レジスタ
;;
;; r4: char *argv[]
;; r5: 残りカードの枚数
;; r6: スキャンする文字(スートか数字)
;; r7: スート役(フラッシュ)フラグ(役候補スートのASCIIコードが入る)
;; r8: ノーペアの数字用フラグ(13ビット使用)
;; r9: ワンペア、ツーペア用フラグ(13ビット使用)
;; r10: スリーカード用フラグ(13ビット使用)
;; r11: フォーカード用フラグ(13ビット使用)
;;
_main:
;; レジスタの初期化
addi r4, r4, 4 ; argv[1] にポインタを進める
lwz r4, 0(r4) ; argv[1] の文字列をレジスタにロード
li r5, 5 ; 残りカード5枚
li r7, 0
li r8, 0
li r9, 0
li r10, 0
li r11, 0
_scan_card:
;; 一文字目(スート)
lbz r6, 0(r4)
bl _scan_suit ; サブルーチン
addi r4, r4, 1
;; 二文字目(数字)
lbz r6, 0(r4)
bl _scan_rank ; サブルーチン
;; 繰り返しの準備
subi r5, r5, 1
cmpli cr7, r5, 0
beq cr7, _show_hand ; 5枚チェックし終えたら役を表示する
addi r4, r4, 1
b _scan_card ; 繰り返し
;; スートのスキャン
_scan_suit:
;; 最初のカードならそのままフラグをセット
cmpli cr7, r5, 5
beq cr7, _scan_first_suit
;; 二枚目以降
cmpli cr7, r7, 0 ; フラグがゼロならフラッシュの可能性もゼロ
beqlr cr7
cmpl cr7, r7, r6 ; 前のスートと同じなら戻る
beqlr cr7
li r7, 0 ; 前のスートと異なるならフラグをクリア
blr ; サブルーチン終了
;; 最初のカードのスートのスキャン
_scan_first_suit:
add r7, r0, r6 ; r0 は 0 とみなされるので、r7 = r6
blr ; サブルーチン終了
;; ランクのスキャン
_scan_rank:
;; ASCIIコードを 0-12 の整数にする
cmpli cr7, r6, 65 ; 'A'
beq cr7, _scan_rank_ace
cmpli cr7, r6, 84 ; 'T'
beq cr7, _scan_rank_ten
cmpli cr7, r6, 74 ; 'J'
beq cr7, _scan_rank_jack
cmpli cr7, r6, 81 ; 'Q'
beq cr7, _scan_rank_queen
cmpli cr7, r6, 75 ; 'K'
beq cr7, _scan_rank_king
;; 2-9
subi r6, r6, 49
b _scan_rank_body
_scan_rank_ace:
li r6, 0
b _scan_rank_body
_scan_rank_ten:
li r6, 9
b _scan_rank_body
_scan_rank_jack:
li r6, 10
b _scan_rank_body
_scan_rank_queen:
li r6, 11
b _scan_rank_body
_scan_rank_king:
li r6, 12
b _scan_rank_body
;; r15: ランクのビット表現
;; r16: 論理演算結果
_scan_rank_body:
li r0, 1
slw r15, r0, r6 ; 左シフト (1<<r6)
;; フォーカード:同ランクのカードが三枚あるかチェック
and r16, r10, r15
cmpli cr7, r16, 0
bgt cr7, _switch_four_kind_flag
;; スリーカード:同ランクのカードが二枚あるかチェック
and r16, r9, r15
cmpli cr7, r16, 0
bgt cr7, _switch_three_kind_flag
;; ワンペア:同ランクのカードが一枚あるかチェック
and r16, r8, r15
cmpli cr7, r16, 0
bgt cr7, _switch_one_pair_flag
;; ノーペア
or r8, r8, r15 ; ビットフラグを立てる
blr ; サブルーチン終了
;; ワンペア
_switch_one_pair_flag:
or r9, r9, r15 ; ビットフラグを立てる
xor r8, r8, r15 ; ノーペアのフラグを下ろす
blr ; サブルーチン終了
;; スリーカード
_switch_three_kind_flag:
or r10, r10, r15 ; ビットフラグを立てる
xor r9, r9, r15 ; ワンペアのフラグを下ろす
blr ; サブルーチン終了
;; フォーカード
_switch_four_kind_flag:
or r11, r11, r15 ; ビットフラグを立てる
xor r8, r8, r15 ; スリーカードのフラグを下ろす
blr ; サブルーチン終了
;; 役の表示
_show_hand:
;; フラッシュ、ストレートフラッシュ、
;; ロイヤルフラッシュのチェック
cmpli cr7, r7, 0
bne cr7, _check_flushes
;; フォーカードのチェック
andi. r0, r11, 8191 ; (1<<13)-1
cmpli cr7, r0, 0
bgt cr7, _show_four_kind
;; フルハウス、スリーカードのチェック
andi. r0, r10, 8191
cmpli cr7, r0, 0
bgt cr7, _check_full_house_or_three_kind
;; ワンペア、ツーペアのチェック
andi. r0, r9, 8191
cmpli cr7, r0, 0
bgt cr7, _check_one_or_two_pair
;; ストレートのチェック
bl _check_straight
cmpli cr7, r2, 0
bne cr7, _show_straight
;; ノーペア
b _show_no_pair
;; フラッシュ、ストレートフラッシュ、ロイヤルフラッシュ
_check_flushes:
;; ロイヤルフラッシュのチェック
;; ランク ATJQK のビットマスク
li r0, 1|(1<<9)|(1<<10)|(1<<11)|(1<<12)
and r2, r8, r0
cmpl cr7, r2, r0
beq cr7, _show_royal_flush
;; ストレートフラッシュのチェック
bl _check_straight
cmpli cr7, r2, 0
bne cr7, _show_straight_flush
;; フラッシュ
b _show_flush
;; ストレートのチェック(サブルーチン)
;; ストレートなら r2 > 0 にして戻る
_check_straight:
;; ビットマスク 11111 を左にずらしながら9回AND演算する
li r0, (1<<5)-1 ; ビットマスク
li r2, 0 ; 左シフト数
_find_straight:
slw r15, r0, r2 ; 左シフト
and r17, r8, r15 ; ノーペア用フラグを調べる
cmpl cr7, r17, r15
beq cr7, _found_straight
addi r2, r2, 1 ; 次のループの準備
cmpli cr7, r2, 9
ble cr7, _find_straight
li r2, 0 ; 5つの連続した数字がなかった
blr ; サブルーチン終了
_found_straight:
li r2, 1 ; 5つの連続した数字を発見
blr ; サブルーチン終了
;; フルハウスかスリーカード
_check_full_house_or_three_kind:
;; ワンペアがあればフルハウス
andi. r0, r9, 8191
cmpli cr7, r0, 0
bgt cr7, _show_full_house
b _show_three_kind
;; ワンペアかツーペア
_check_one_or_two_pair:
li r0, 1 ; これをシフト
li r2, 0 ; 左シフト数
li r16, 0 ; ペアの数
;; ペア用フラグからペアの数をカウントする
_find_pairs:
slw r15, r0, r2
and r17, r9, r15
addi r2, r2, 1
cmpli cr7, r17, 0
bgt cr7, _found_pair
cmpli cr7, r2, 13 ; 0-12 の 13 回チェック
ble cr7, _find_pairs
;; ペアの数で分岐
cmpli cr7, r16, 1
beq cr7, _show_one_pair
b _show_two_pair
;; 見つけたペアの数を増加
_found_pair:
addi r16, r16, 1
b _find_pairs ; 戻る
;; ノーペア
_show_no_pair:
lis r4, hi16(no_pair)
addi r4, r4, lo16(no_pair)
li r5, 8
b _print_and_exit
;; ワンペア
_show_one_pair:
lis r4, hi16(one_pair)
addi r4, r4, lo16(one_pair)
li r5, 9
b _print_and_exit
;; ツーペア
_show_two_pair:
lis r4, hi16(two_pair)
addi r4, r4, lo16(two_pair)
li r5, 9
b _print_and_exit
;; スリーカード
_show_three_kind:
lis r4, hi16(three_kind)
addi r4, r4, lo16(three_kind)
li r5, 16
b _print_and_exit
;; ストレート
_show_straight:
lis r4, hi16(straight)
addi r4, r4, lo16(straight)
li r5, 9
b _print_and_exit
;; フラッシュ
_show_flush:
lis r4, hi16(flush)
addi r4, r4, lo16(flush)
li r5, 6
b _print_and_exit
;; フルハウス
_show_full_house:
lis r4, hi16(full_house)
addi r4, r4, lo16(full_house)
li r5, 11
b _print_and_exit
;; ストレートフラッシュ
_show_straight_flush:
lis r4, hi16(straight_flush)
addi r4, r4, lo16(straight_flush)
li r5, 15
b _print_and_exit
;; フォーカード
_show_four_kind:
lis r4, hi16(four_kind)
addi r4, r4, lo16(four_kind)
li r5, 15
b _print_and_exit
;; ロイヤルフラッシュ
_show_royal_flush:
lis r4, hi16(royal_flush)
addi r4, r4, lo16(royal_flush)
li r5, 12
b _print_and_exit
;; 文字列を出力して終了する
;; r4 に文字列のアドレスを、r5 に文字列の長さをセットしておく
_print_and_exit:
;; sys_write()
li r3, 1 ; 標準出力
li r0, 4 ; sys_write
sc ; 呼び出し
b _exit
_exit:
;; sys_exit()
li r3, 0
li r0, 1
sc
;; 定数
.data
.align 2
no_pair:
.asciz "No pair\n"
.align 2
one_pair:
.asciz "One pair\n"
.align 2
two_pair:
.asciz "Two pair\n"
.align 2
three_kind:
.asciz "Three of a kind\n"
.align 2
straight:
.asciz "Straight\n"
.align 2
flush:
.asciz "Flush\n"
.align 2
full_house:
.asciz "Full house\n"
.align 2
four_kind:
.asciz "Four of a kind\n"
.align 2
straight_flush:
.asciz "Straight flush\n"
.align 2
royal_flush:
.asciz "Royal flush\n"
.align 2
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | import std.stdio;
import std.string;
string poker(string cards){
auto suit = "SDHC";
auto rankOrder = "A23456789TJQK";
auto transRankOrder = "abcdefghijklm";
auto transRank = translate(cards, maketrans(rankOrder, transRankOrder), suit).sort;
int[char] rankCount;
foreach(c; transRank){
rankCount[c]++;
}
auto pairPattern = rankCount.values.sort;
auto hand = pairPattern == [1, 1, 1, 2] ? "One pair" :
pairPattern == [1, 2, 2] ? "Two pair" :
pairPattern == [1, 1, 3] ? "Three of a kind" :
pairPattern == [2, 3] ? "Full house" :
pairPattern == [1, 4] ? "Four of a kind" : "";
if(hand == ""){
auto isFlush = cards[0] == cards[2] && cards[0] == cards[4] &&
cards[0] == cards[6] && cards[0] == cards[8];
hand = find(transRankOrder, transRank) != -1 ?
(isFlush ? "Straight flush" : "Straight") :
transRank == (transRankOrder[0] ~ transRankOrder[($ - 4)..$]) ?
(isFlush ? "Royal flush" : "Straight") :
(isFlush ? "Flush" : "No pair");
}
return hand;
}
void main(){
writefln(poker("SQSJSASKST")); // Royal flush
writefln(poker("D9D7D6D5D8")); // Straight flush
writefln(poker("C2D2S2H3H2")); // Four of a kind
writefln(poker("C2D3S2H3H2")); // Full house
writefln(poker("S9S4S8STSJ")); // Flush
writefln(poker("C4H7D5S6H3")); // Straight
writefln(poker("S6H6C5DQC6")); // Three of a kind
writefln(poker("S6HQC5DQC6")); // Two pair
writefln(poker("S6H4C5DQC6")); // One pair
writefln(poker("SJSQSKSAC2")); // No pair
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | import sys
def f(c):
d = {'A': '1', 'T': 'a', 'J': 'b', 'Q': 'c', 'K': 'd'}
s = len(set([c[i] for i in range(0,10,2)])) == 1
r = ''.join(sorted([d[c[i]] if c[i] in d else c[i] for i in range(1,11,2)]))
l = len(set(r))
if l == 2:
print 'Four of a kind' if r.count(r[0]) in [1,4] else 'Full house'
elif l == 5:
if '123456789abcd 1abcd'.find(r) >= 0:
print ('Royal flush 'if r == '1abcd' else 'Straight flush') if s else 'Straight'
elif s:
print 'Flush'
else:
print 'No pair'
elif s:
print 'Flush'
elif l == 4:
print 'One pair'
elif l == 3:
print 'Three of a kind' if [i for i in set(r) if r.count(i) >= 3] else 'Two pair'
f(sys.argv[1])
|
こういうときに便利なスライスの記法を思い出したのと 文字の置換も必要なかったので、ちょっと書き直しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import sys
def f(c):
s = len(set(c[0::2])) == 1
r = ''.join(sorted(c[1::2]))
l = len(set(r))
if l == 2:
print 'Four of a kind' if r.count(r[0]) in [1,4] else 'Full house'
elif l == 5:
if '2345A23456789T789JT89JQT9JKQTAJKQT'.find(r) >= 0:
print ('Royal flush' if r == 'AJKQT' else 'Straight flush') if s else 'Straight'
elif s:
print 'Flush'
else:
print 'No pair'
elif s:
print 'Flush'
elif l == 3:
print 'Three of a kind' if [i for i in set(r) if r.count(i) >= 3] else 'Two pair'
else:
print 'One pair'
f(sys.argv[1])
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | function doukaku121(hand){
var S = [], R = [], sd = {S:0, H:1, D:2, C:3}, rd = {A:1, T:10, J:11, Q:12, K:13};
hand.toUpperCase().replace(/([SHDC])([2-9TJQKA])/g, function(_, s, r){
++S[s = sd[s]] || (S[s] = 1);
++R[r = rd[r] || r] || (R[r] = 1);
});
var flush = /5/.test(S +'');
if(/1,1,1,1,1/.test(R +','+ R[1]))
return flush ? (R[1] && R[13] ? 'Royal ' : '') +'Straight Flush' : 'Straight';
switch((R = R.sort(function(x, y){ return y - x }))[0]){
case 1: return flush ? 'Flush' : 'No Pair';
case 2: return R[1] == 2 ? 'Two Pair' : 'One Pair';
case 3: return R[1] == 2 ? 'Full House' : 'Three of a Kind';
case 4: return 'Four of a Kind';
}
}
|
sedで書けそうな気がするのですが、めんどくさがってsortを使うことにしたのでシェルスクリプトになってしまいました。 行が長いです。ごめんなさい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #!/bin/sh
if echo $1 | grep -q -v '^\([CDHS][A2-9TJQK]\)\{5\}$'; then
echo 'Error: Invalid hand'
exit 1
fi
declare n=`echo $1 | sed 's/[CDHS]\(.\)/\1\n/g' | tr 'A2-9TJQK' 'a-m' | sort | tr -d '\n' | sed -e '/[a-e]$/y/abcde/ijklm/' -e '/[f-i]$/y/abcdefghi/efghijklm/' -e '/[jk]$/y/abcdefghijk/cdefghijklm/' -e '/l$/y/abcdefghijkl/bcdefghijklm/'`
if echo $1 | grep -q '\(.\).\(\1.\)\{4\}'; then
echo $n | sed -e 's/ajklm/Royal flush/' -e 's/ijklm/Straight flush/' -e 's/....m/Flush/'
elif echo $n | grep -q '[ai]jklm'; then
echo Straight
elif echo $n | grep -q '\(.\)\1\1\1'; then
echo Four of a kind
else
echo $n | sed -e 's/\(.\)\1\1//' -e 's/\(.\)\1//g' -e 's/^.....$/No pair/' -e 's/^...$/One pair/' -e 's/^..$/Three of a kind/' -e 's/^.$/Two pair/' -e 's/^$/Full house/'
fi
|
その後、まじめにsedで書いてみました。こっちのほうがきれいかも。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | #!/bin/sed -f
/^\([CDHS][A2-9TJQK]\)\{5\}$/!b
/\([CDHS][A2-9TJQK]\).*\1/b
/\(.\).\(\1.\)\{4\}/{
s/^/X/
}
s/[CDHS]//g
s/\([2468TQK]\+\)\([A3579J]\+\)/\2\1/g
s/\([2468TQK]\+\)\([A3579J]\+\)/\2\1/
s/\([3478JQK]\+\)\([A2569T]\+\)/\2\1/g
s/\([3478JQK]\+\)\([A2569T]\+\)/\2\1/
s/\([5-8K]\+\)\([A2349TJQ]\+\)/\2\1/g
s/\([5-8K]\+\)\([A2349TJQ]\+\)/\2\1/
s/\([9TJQK]\+\)\([A2-8]\+\)/\2\1/g
s/\([9TJQK]\+\)\([A2-8]\+\)/\2\1/
/[2-5]$/y/A2345/9TJQK/
/[6-9]$/y/A23456789/56789TJQK/
/[TJ]$/y/A23456789TJ/3456789TJQK/
/Q$/y/A23456789TJQ/23456789TJQK/
s/^\(.\)\1\1\1K$\|^.KKKK$/Four of a kind/
s/\(.\)\1\+//g
s/^$/Full house/
s/^.$/Two pair/
s/^..$/Three of a kind/
s/^...$/One pair/
s/^[A9]TJQK$/Straight/
s/^.....$/No pair/
s/^XATJQK$/Royal flush/
s/^X9TJQK$/Straight flush/
s/^X.....$/Flush/
|
素直に
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #light
open List
let poker cs =
let is_all_elems_same l = tryfind ((<>) (hd l)) (tl l) |> Option.is_none
let tally l =
let h = Hashtbl.create (length l)
for x in l do
if Hashtbl.mem h x then Hashtbl.replace h x (Hashtbl.find h x + 1)
else Hashtbl.add h x 1
h
(* 手札の情報をスートとランクの 2 つの情報に分離 *)
let maxi = String.length cs - 1
let suit = [for i in 0..2..maxi -> cs.[i]]
let rank = [for i in 1..2..maxi -> String.index "A23456789TJQK" cs.[i] + 1]
|> sort (-)
(* 判定基準となる条件役を算出 *)
let rst = rank = [1;10;11;12;13]
let flu = is_all_elems_same suit
let str = is_all_elems_same (mapi (fun i x -> x - i) rank)
let pnt = [for p in (tally rank) when p.Value > 1 -> p.Value] |> sort (-)
(* 役判定 *)
match rst, flu, str, pnt with
true, true, _, _ -> "Royal flush"
| _, true, true, _ -> "Straight flush"
| _, _, _, [4] -> "Four of a kind"
| _, _, _, [2;3] -> "Full house"
| _, true, _, _ -> "Flush"
| _, _, true, _ -> "Straight"
| _, _, _, [3] -> "Three of a kind"
| _, _, _, [2;2] -> "Two pair"
| _, _, _, [2] -> "One pair"
| _ -> "No pair"
let _ =
let ($) f g x = f (g x)
["SQSJSASKST";"D9D7D6D5D8";"C2D2S2H3H2";"C2D3S2H3H2";"S9S4S8STSJ"
"C4H7D5S6H3";"S6H6C5DQC6";"S6HQC5DQC6";"S6H4C5DQC6";"SJSQSKSAC2"]
|> iter (printfn "%s" $ poker)
|
echo Poker('SQSJSASKST');
パラメータチェックを怠っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | <?php
function Poker($c)
{
CSort($c);
if (IsFlush($c)) {
if (IsStraight($c)) {
if ($c[1] == 'A') {
return 'Royal flush';
}
return 'Straight flush';
}
return 'Flush';
} else {
if (IsStraight($c)) {
return 'Straight';
}
$wk = array();
$wk[$c[1]]++;
$wk[$c[3]]++;
$wk[$c[5]]++;
$wk[$c[7]]++;
$wk[$c[9]]++;
arsort($wk);
switch (array_shift($wk).array_shift($wk)) {
case '41': return 'Four of a kind';
case '32': return 'Full house';
case '31': return 'Three of a kind';
case '22'; return 'Two pair';
case '21'; return 'One pair';
}
}
return 'No pair';
}
function IsFlush($c)
{
if ($c[0] == $c[2] && $c[0] == $c[4] && $c[0] == $c[6] && $c[0] == $c[8]) {
return TRUE;
}
return FALSE;
}
function IsStraight($c)
{
$rank = 'A23456789TJQK';
$num = $c[1].$c[3].$c[5].$c[7].$c[9];
if (strpos($rank, $num) !== FALSE || $num == 'ATJQK') {
return TRUE;
}
return FALSE;
}
function CSort(&$c)
{
$rep = array('1'=>'A', '10'=>'T', '11'=>'J', '12'=>'Q', '13'=>'K');
$wk = array($c[0].$c[1] => $c[1], $c[2].$c[3] => $c[3],
$c[4].$c[5] => $c[5], $c[6].$c[7] => $c[7],
$c[8].$c[9] => $c[9]);
$wk = str_ireplace($rep, array_flip($rep), $wk);
asort($wk);
$c = '';
foreach ($wk as $key => $value) {
$c .= $key;
}
}
?>
|
rankとsuitを分離して扱いました.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | def poker(hand)
def one_pair(rank, count = 0)
rank.values.map{|x| count += 1 if x.size == 2}
count == 1
end
def two_pair(rank, count = 0)
rank.values.each{|x| count += 1 if x.size == 2}
count == 2
end
def three_cards(rank)
rank.values.map{|x| x.size == 3 ? true : nil}.compact.shift
end
def straight(rank)
rank.size == 5 ? rank.keys.sort.first + 4 == rank.keys.sort.last : false
end
def flush(suit); suit.size == 1 ;end
def fourcards(rank)
rank.values.map{|x| x.size == 4 ? true : nil}.compact.shift
end
def convert(char)
case char
when 'T': 10
when 'J': 11
when 'Q': 12
when 'K': 13
when 'A': 14
else
char.to_i
end
end
def div_suit_and_rank(hand)
suit_hash, rank_hash = Hash.new, Hash.new
cards = hand.split('')
Array.new(hand.size.div(2)){|i| 2*i}.each{|i|
suit = cards[i]
rank = convert(cards[i+1])
eval("suit_hash[suit] #{(suit_hash[suit] ? '<< rank' : '= [rank]')}")
eval("rank_hash[rank] #{(rank_hash[rank] ? '<< suit' : '= [suit]')}")
}
[suit_hash, rank_hash]
end
suit, rank = *div_suit_and_rank(hand)
if straight(rank)
"#{rank.keys.sort.first == 10 ? 'Loyal ' : ''}Straight #{(flush(suit) ? 'Flush' : '')}"
elsif fourcards(rank)
"Four of a Kind"
elsif three_cards(rank) and one_pair(rank)
"Full House"
elsif flush(suit)
"Flush"
elsif three_cards(rank)
"Three of a Kind"
elsif two_pair(rank)
"Two Pair"
elsif one_pair(rank)
"One Pair"
else
"No Pair"
end
end
hands = ['SQSJSASKST', 'D9D7D6D5D8', 'C2D2S2H3H2', 'C2D3S2H3H2', 'S9S4S8STSJ', 'C4H7D5S6H3', 'S6H6C5DQC6', 'S6HQC5DQC6', 'S6H4C5DQC6', 'SJSQSKSAC2']
hands.each{|x| puts poker(x)}
|
残念ながらこれだと、xAx2x3x4x5の形のランクの並びがストレートと判断されないようです。
Aは最初または最後とされているみたいですね。
確かに, Aを14としたのが敗因でした. straightメソッドに場合分けを追加する必要がありますね.
ストレートの判定がなかなかきれいにまとまりませんね。ソートしておいて隣り合う数の差で判断してみましたが……うーん。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | import Data.List as List
hand :: String -> (String, Bool)
hand cards =
(case kinds of
[1, 4] -> "Four of a kind"
[2, 3] -> "Full house"
[1, 1, 3] -> "Three of a kind"
[1, 2, 2] -> "Two pair"
[1, 1, 1, 2] -> "One pair"
otherwise ->
case rdiff of
[1, 1, 1, 1] | head ranks == 10 && isFlush -> "Royal"
| True -> "Straight"
[1, 1, 1, 9] -> "Straight"
otherwise -> "No pair"
, isFlush)
where suits = List.nub [cards !! n | n <- [0,2..8]]
isFlush = length suits == 1
ranks = List.sort [rankToInt $ cards !! n | n <- [1,3..9]]
rankToInt r = case List.elemIndex r "23456789TJQKA" of Just n -> n+2
kinds = List.sort $ map length $ List.group ranks
rdiff = zipWith (-) (tail ranks) ranks
main = mapM test ["SQSJSASKST", "D9D7D6D5D8", "C2D2S2H3H2", "C2D3S2H3H2",
"S9S4S8STSJ", "C4H7D5S6H3", "S6H6C5DQC6", "S6HQC5DQC6",
"S6H4C5DQC6" ,"SJSQSKSAC2"]
where test s = putStrLn (s ++ " => " ++ (showHand $ hand s))
showHand ("No pair", True) = "Flush"
showHand (s, True) = s ++ " flush"
showHand (s, False) = s
|
permutationとパターンマッチで簡単に.効率は犠牲に...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | pokerHand([X,X,X,X,X], R, 'Royal flush') :-
permutation(R, ['T','J','Q','K','A']).
pokerHand([X,X,X,X,X], R, 'Straight flush') :-
sub_atom('A23456789TJQK', _, 5, _, A),
atom_chars(A, P), permutation(R, P).
pokerHand([X,X,X,X,X], _, 'Flush').
pokerHand(_, R, 'Straight') :-
sub_atom('A23456789TJQKA', _, 5, _, A),
atom_chars(A, P), permutation(R, P).
pokerHand(_, R, 'Four of a kind' ) :- permutation(R, [X,X,X,X,_]).
pokerHand(_, R, 'Full house' ) :- permutation(R, [X,X,X,Y,Y]).
pokerHand(_, R, 'Three of a kind') :- permutation(R, [X,X,X,_,_]).
pokerHand(_, R, 'Two pair' ) :- permutation(R, [X,X,Y,Y,_]).
pokerHand(_, R, 'One pair' ) :- permutation(R, [X,X,_,_,_]).
pokerHand(_, _, 'No pair' ).
poker(Card) :-
atom_chars(Card, [S1,R1,S2,R2,S3,R3,S4,R4,S5,R5]),
pokerHand([S1,S2,S3,S4,S5], [R1,R2,R3,R4,R5], H), !,
writeln(H).
|
なるほど。permutationでリスト中の順番に関係なくパターンとつきあわせることができるんですか。 ソートとかしなくてもいいんだ。(効率を考えなければ) 勉強になります。
初投稿です。Cleanです。この辺のライブラリを使ってます。
http://sourceforge.net/projects/cleanoptenv
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | module Main
import System, Int, Char, String, List, Misc, MergeSort, ValueCast
Start
| flush cards
| straight cards
| 14 == num (head cards)
= "Royal flush"
= "Straight flush"
= "Flush"
| straight cards
= "Straight"
| 4 == head groups
= "Four of a kind"
| 3 == head groups
| 2 == groups !! 1
= "Full house"
= "Three of a kind"
| 2 == head groups
| 2 == groups !! 1
= "Two pair"
= "One pair"
= "No pair"
where
cards = sortBy (>) $ parseCards getCommandLine.[1]
groups = sortBy (>) $ map length $ groupCards [[]] 0 cards
:: Card = Card !Char !Int //suit num(2..14)
instance < Card where
(<) (Card s0 n0) (Card s1 n1) = n0 < n1
suit (Card s n) = s
num (Card s n) = n
parseCards t = p 0
where
l = size t
p i | i >= l = []
= [Card s n: p (i+2)]
where
s = t.[i]
n = case t.[i+1] of
'A' = 14
'K' = 13
'Q' = 12
'J' = 11
'T' = 10
c = toInt (c - '0')
groupCards ls _ [] = ls
groupCards [l:ll] m [c=:Card s n: rest]
| m == n = groupCards [[c:l]:ll] n rest
= groupCards [[c],l:ll] n rest
flush cards = and $ zipWith (==) suits (tail suits)
where
suits = map suit cards
straight cards = (and $ zipWith (\a b = a == b + 1) nums (tail nums))
|| caseAce nums
where
nums = map num cards
caseAce [14,5,4,3,2] = True
caseAce _ = False
|
初めにこのお題を思いついたときは、ただのif文の山をどう片付けるかという要素しかないものかと思っていたのですが、試しに自分で解いたときに、
(1)フラッシュかどうかをどう判断するか
(2)ストレートかどうかをどう判断するか
(3)ランクの構造はどうなっているか
(4)上記3つの判断要素をどう組み合わせるか
などが、言語によって特色がでそうなので出題してみました。
(4)の処理はHaskell、OCaml、Scalaなどパターンマッチがある言語や、PythonやD言語などリストの一致を簡単に比較できる言語では書きやすそうに見えましたが、#5186 shimakumaさんのJavaScript版はパターンマッチ/リスト比較など無しでかなりコンパクトにまとめていてうまいと思いました。
そんな中、#5187 GEOJさんのA2-9TJQKをa-mに置換して扱うというアイデアが面白かったので、Perlで真似してみました。
ランクの構造は、ソートした後に正規表現を使って調べています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #!/usr/bin/perl
($_ = shift) =~ tr /A2-9TJQK/a-m/;
$rank = join('', sort(split /[SCDH]/));
$flag = (/^(.).((\1).){4}/) * 4 + ($rank eq "ajklm") * 2 + ("abcdefghijklm" =~ /$rank/);
die "Royal flush\n" if ($flag == 6);
die "Straight flush\n" if ($flag == 5);
die "Flush\n" if ($flag == 4);
die "Straight\n" if ($flag);
die "Four of a kind\n" if ($rank =~ /(.)\1{3}/);
die "Full house\n" if ($rank =~ /((.)\2\2(.)\3)|((.)\5(.)\6\6)/);
die "Three of a kind\n" if ($rank =~ /(.)\1\1/);
die "Two pair\n" if ($rank =~ /(.)\1.?(.)\2/);
die "One pair\n" if ($rank =~ /(.)\1/);
die "No pair\n";
|
data使いたがりなhaskellコード。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | import System
import List(sort,group,elemIndex)
import Maybe(fromJust)
data Card = Card {suits::Suits,rank::Int} deriving Show
data Suits = S | D | H | C deriving (Read,Eq,Show)
data Hand = RF | STF | FK | FH | F | ST | TK | TP | OP | NO
read_cards :: String -> [Card]
read_cards str = map read_card $ split_2 str
where
read_card [s,r] = Card (read [s])
(fromJust (elemIndex r "DD23456789TJQKA"))
split_2 [] = []
split_2 list = let (hd,rest) = splitAt 2 list in hd : split_2 rest
instance Show Hand where
show h = case h of
RF -> "Royal flush"
STF -> "Straight flush"
FK -> "Four of a kind"
FH -> "Full House"
F -> "Flush"
ST -> "Straight"
TK -> "Three of a kind"
TP -> "Two pair"
OP -> "One pair"
NO -> "No pair"
hand :: [Card] -> Hand
hand cards
| check_st && check_flush && head rank_seq == 10 = RF
| check_st && check_flush = STF
| max_group == 4 = FK
| sort group_count == [2,3] = FH
| check_flush = F
| check_st = ST
| max_group == 3 = TK
| pair_count == 2 = TP
| pair_count == 1 = OP
| otherwise = NO
where
rank_seq = sort $ map rank cards
groups = group rank_seq
group_count = map length groups
max_group = foldl1 max group_count
pair_count = length (filter (\l->length l == 2) groups)
check_flush = all (\c->suits c==suits (head cards)) cards
check_st = normal || rank_seq == [2,3,4,5,14]
where
normal = and $ zipWith (\a b->a-b == head rank_seq) rank_seq [0..]
main = getArgs >>= print . hand . read_cards . head
-- Test
test = zip testlist (map (hand .read_cards) testlist)
testlist = ["SQSJSASKST",
"D9D7D6D5D8",
"C2D2S2H3H2",
"C2D3S2H3H2",
"S9S4S8STSJ",
"C4H7D5S6H3",
"S6H6C5DQC6",
"S6HQC5DQC6",
"S6H4C5DQC6",
"SJSQSKSAC2"]
|
短さ優先。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | ranks = []
1.step(10, 2) do |i| ranks << ARGV[0][i, 1] end
rank_hash = Hash.new(0)
ranks.each do |rank| rank_hash[rank] += 1 end
flush = ARGV[0].count(ARGV[0][0,1].to_s) == 5
straight = ("23456789AJKQT".include? ranks.sort!.to_s or "2345A".include? ranks.to_s)
case
when (ranks.to_s == "AJKQT" and flush) then puts "Royal Flush"
when (straight and flush) then puts "Straight Flush"
when rank_hash.values.max == 4 then puts "Four of a Kind"
when (rank_hash.values.max == 3 and rank_hash.values.include? 2) then puts "Full House"
when flush then puts "Flush"
when straight then puts "Straight"
when rank_hash.values.max == 3 then puts "Three of a Kind"
when rank_hash.values.to_s.count("2") == 2 then puts "Two Pair"
when rank_hash.values.max == 2 then puts "One Pair"
else puts "No Pair"
end
|
Schemeがないので, 適当なパターンマッチで書いたものを投稿します
エラー判定はしていないので "ASASASASAS"等も受け入れます
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | (use srfi-1)
(use util.match)
(define (poker hand)
(define (rank->num a)
(cond [(char-set-contains? #[\d] a) (digit->integer a)]
[(char=? #\A a) 14]
[(char=? #\T a) 10]
[(char=? #\J a) 11]
[(char=? #\Q a) 12]
[(char=? #\K a) 13]
[else a]))
(define (decision nums suits)
(let1 flags (map - (cdr nums) nums) ;;次のカードとの差
(cond ((fold (lambda (a r) (and (eq? a (car suits)) r)) #t suits) ;; FLUSH
(match flags
((1 1 1 1) (if (= 10 (car nums)) "Royal flush" "Straight flush"))
((1 1 1 9) "Straight flush") ;; 2 3 4 5 14用
(else "Flush")))
(else
(match flags
((0 0 0 _) "Four of a kind")
((_ 0 0 0) "Four of a kind")
((0 0 _ 0) "Full house")
((0 _ 0 0) "Full house")
((1 1 1 1) "Straight")
((1 1 1 9) "Straight") ;; 2 3 4 5 14用
((_ _ 0 0) "Three of a kind")
((_ 0 0 _) "Three of a kind")
((0 0 _ _) "Three of a kind")
(else
(match (sort flags <)
((0 0 _ _) "Two pair")
((0 _ _ _) "One pair")
(else "No pair"))))))))
(receive (nums suits)
(partition number? (map rank->num (string->list hand)))
(decision (sort nums <) suits)))
(map poker
'("SQSJSASKST" "D9D7D6D5D8" "C2D2S2H3H2" "C2D3S2H3H2" "S9S4S8STSJ"
"C4H7D5S6H3" "S6H6C5DQC6" "S6HQC5DQC6" "S6H4C5DQC6" "SJSQSKSAC2"))
;=>
;("Royal flush" "Straight flush" "Four of a kind" "Full house" "Flush"
; "Straight" "Three of a kind" "Two pair" "One pair" "No pair")
|
array_count_values は、こんなのあるかな?と思ってマニュアル探したらやっぱりあった。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | #!/usr/bin/php
<?php
$suits = array();
$ranks = array();
for ($i = 0; $i < 10; $i += 2) {
$suits[] = $argv[1][$i];
$ranks[] = strtr($argv[1][$i+1], "TJQKA", "ABCDE");
}
sort($suits);
sort($ranks);
$suitCnt = array_count_values($suits);
asort($suitCnt);
$rankCnt = array_count_values($ranks);
arsort($rankCnt);
$straight = false;
$flush = false;
$suitHist = array_values($suitCnt);
if ($suitHist[0] == 5) {
$flush = true;
}
$rankHist = array_values($rankCnt);
if (strstr("23456789ABCDE,2345E", implode('',$ranks))) {
$straight = true;
}
$hand = '';
if ($straight && $flush) {
if (implode('', $ranks) == 'ABCDE') {
$hand = "Royal straight flush";
} else {
$hand = "Straight flush";
}
} else if ($rankHist[0] == 4) {
$hand = "Four of a kind";
} else if ($rankHist[0] == 3 && $rankHist[1] == 2) {
$hand = "Full house";
}
if ($hand == '') {
if ($flush) {
$hand = "Flush";
} else if ($straight) {
$hand = "Straight";
} else if ($rankHist[0] == 3) {
$hand = "Three of a kind";
} else if ($rankHist[0] == 2 && $rankHist[1] == 2) {
$hand = "Two pairs";
} else if ($rankHist[0] == 2) {
$hand = "One pair";
} else {
$hand = "No Pair";
}
}
echo $hand . "\n";
?>
|
素直に書いてみた。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | class Poker
def initialize str
suits=[]
nums=[]
str.scan(/[SDHCTJQKA0-9]{2}/).each{|card|
tmp=card.scan(/./)
num=case tmp[1]
when "T": 10
when "J": 11
when "Q": 12
when "K": 13
when "A": 1
else tmp[1].to_i
end
suits << tmp[0]
nums << num
}
@cards = {
:suit=>suits,
:num=>nums,
:layer => nums.inject({}){|result,n| # [1,2,2,2,3,3,4] => [1,3,2,1]
result[n]=0 if !result[n]
result[n]+=1
result
}.values
}
end
def one_pair
@cards[:layer].max == 2 && @cards[:layer].length == 4
end
def two_pair
@cards[:layer].max == 2 && @cards[:layer].length == 3
end
def three_card
@cards[:layer].max == 3 && @cards[:layer].length == 3 # not full house
end
def four_card
@cards[:layer].max == 4 && @cards[:layer].length == 2
end
def full_house
@cards[:layer].max == 3 && @cards[:layer].length == 2
end
def five_card
@cards[:layer].max == 5 && @cards[:layer].length == 1
end
def straight
((1..13).to_a.join(" ")).include?(@cards[:num].sort.join(" "))
end
def flush
@cards[:suit].uniq.length == 1
end
def royal_straight_flush
flush() && @cards[:num].sort == [1,10,11,12,13]
end
def cards_rank
# p @cards
case
when (royal_straight_flush()) : "Royal Straight Flush"
when (straight() && flush()): "Straight Flush"
when (four_card()): "Four of a kind"
when (full_house()): "Full house"
when (flush()) : "Flush"
when (straight()) : "Straight"
when (three_card()): "Three of a kind"
when (two_pair()) : "Two pair"
when (one_pair()) : "One pair"
else "No pair"
end
end
end
arr="SQSJSASKST D9D7D6D5D8 C2D2S2H3H2 C2D3S2H3H2 S9S4S8STSJ C4H7D5S6H3 S6H6C5DQC6 S6HQC5DQC6 S6H4C5DQC6 SJSQSKSAC2".split(/\s/)
arr.each{|cards|
puts Poker.new(cards).cards_rank
}
# str=ARGV.shift
# puts poker(str)
|
しまった。ジョーカーないんだからファイブカードになるはずないし、あったとしてもこのチェックじゃダメだ。
結構綺麗にかけたんじゃないかと自負しています。
パターンマッチ様々です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | import List
import Maybe
import System.Environment
card str= map (\(x:y:_)-> (x,rankInt y)) $ every 2 str
testData = "SQSJSASKST"
allRank = "_A23456789TJQK"
rankInt char = fromJust (elemIndex char allRank)
every n xs = unfoldr f xs
where
f [] = Nothing
f cs = Just (splitAt n cs)
isRoyal xs = xs == [1,10,11,12,13]
isStraight xs = (zipWith (-) (tail xs) xs) == [1,1,1,1]
same xs = reverse $ sort $ map (\x-> length $ filter (\a-> x == a) xs) (nub xs)
isFlush xs = nub xs == [head xs]
cardAnalysis xs = let ranks = sort $ map snd xs
suits = map fst xs
royal = isRoyal ranks
straight = isStraight ranks
sameRanks = same ranks
flush = isFlush suits
-- in (flush,royal,straight,sameRanks)
in hand flush royal straight sameRanks
hand True True False _ = "Royal flush"
hand True False True _ = "Straight flush"
hand _ _ _ (4:_) = "Four of a kind"
hand _ _ _ (3:2:_) = "Full house"
hand True _ _ _ = "Flush"
hand _ _ True _ = "Straight"
hand _ True _ _ = "Straight"
hand _ _ _ (3:_) = "Three of a kind"
hand _ _ _ (2:2:_) = "Two Pair"
hand _ _ _ (2:_) = "One Pair"
hand _ _ _ _ = "No Pair"
main = do args <- getArgs
putStrLn $ cardAnalysis $ card $ head args
|
LINQを多用して実現してみました。 これ以上短くできるのかなぁ・・・。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | using System;
using System.Collections.Generic;
using System.Linq;
namespace Doukaku
{
class PorkerJudge
{
protected static char[] Suits = new char[] { 'S', 'D', 'H', 'C' };
protected static char[] Cards = new char[] { '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'J', 'K', 'Q', 'T' };
public static bool IsStraight( IEnumerable<char> numbers)
{
return ("A" + new string(Cards)).IndexOf(new string(numbers.OrderBy(n => n).ToArray())) != -1;
}
public static int CardRank(List<char> numbers)
{
int value = 1;
foreach (char n in numbers.Distinct())
{
value *= numbers.Count(nn => nn == n);
}
return value;
}
public static string Run(string cards)
{
char[] cAry = cards.ToCharArray();
bool isFlush = cAry.Where(c => Suits.Contains(c)).Distinct().Count() == 1;
bool isStraight = IsStraight(cAry.Where(c => Cards.Contains(c)));
List<char> numbers = cAry.Where(c => Cards.Contains(c)).ToList();
bool isRoyal = ! numbers.Intersect( Cards.Take(8) ).Any();
int rank = CardRank(numbers);
if (isStraight && isFlush && isRoyal)
return "Royal flush";
else if (isStraight && isFlush)
return "Straight flush";
if ((from n in numbers select numbers.Count(nn => n == nn)).Contains(4))
return "Four of a kind";
else if (rank == 6)
return "Full house";
else if (isFlush)
return "Flush";
else if (isStraight)
return "Straight";
else if (rank == 3)
return "Three of a kind";
else if (rank == 4)
return "Two pair";
else if (rank == 2)
return "One pair";
return "No pair";
}
}
}
|
合っているかいるかどうかわからないので全組合せを喰わせてみました。
かなり汚いできではありますが、うまくいっているようです。
皆様のコードを参考にさせていただきました。
結果は
Royal flush 4 1/649740
Straight flush 36 1/72193.33
Four of a kind 624 1/4165
Full house 3744 1/694.17
Flush 5108 1/508.8
Straight 10200 1/254.8
Three of a kind 54912 1/47.33
Two pair 123552 1/21.04
One pair 1098240 1/2.37
No pair 1302540 1/2
total 2598960
でした。
全組合せは以下で作りました。
suits = ["S","D","H","C"]
rank = (["A"] + ("2".."9").to_a + ["T","J","Q","K"])
card = []
for i in suits.product(rank)
card << i.join
end
for i in card.combination(5).to_a
puts i.shuffle.join #一応、シャッフル。
end
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | def porker(hand)
narabi =(["0","A"] + ("2".."9").to_a + ["T","J","Q","K"])
def num(a)
(["0","A"] + ("2".."9").to_a + ["T","J","Q","K"]).index(a)
end
tmp = hand.scan(/[SDHCTJQKA2-9]{2}/).map(&:chars).map(&:to_a)
card = Hash.new{|h,k|h[k]=[]}
for i in tmp
i[0]
card[i[0]] << i[1]
end
suuji = Hash.new(0)
for i in card.values.flatten
suuji[i] += 1
end
case
when card.keys.size == 1 && card.values.flatten.sort_by{|a|num(a)}.join(" ") == "A T J Q K"
"Royal flush"
when card.keys.size == 1 && %r(#{suuji.keys.sort_by{|a|num(a)}.join(" ")}) =~ narabi.join(" ")
"Straight flush"
when suuji.select{|k,v|v == 4}.size == 1
"Four of a kind"
when suuji.keys.size == 2
"Full house"
when card.keys.size == 1
"Flush"
when suuji.keys.size == 5 && (%r(#{suuji.keys.sort_by{|a|num(a)}.join(" ")}) =~ narabi.join(" ") ||
suuji.keys.sort_by{|a|num(a)}.join(" ") == "A T J Q K")
"Straight"
when suuji.select{|k,v|v == 3}.size == 1
"Three of a kind"
when suuji.select{|k,v|v == 2}.size == 2
"Two pair"
when suuji.select{|k,v|v == 2}.size == 1
"One pair"
else
"No pair"
end
end
#ruby porker.rb file|SQSJSASKST|なしの場合は__END__以下
if ARGV.size == 1
if File.exist?(ARGV[0])
f = open(ARGV[0])
while f.gets
hand = $_.chomp
puts [hand,porker(hand)].join(" ")
end
else
puts [ARGV[0],porker(ARGV[0])].join(" ")
end
else
while DATA.gets
hand = $_.chomp
puts [hand,porker(hand)].join(" ")
end
end
__END__
SQSJSASKST
D9D7D6D5D8
C2D2S2H3H2
C2D3S2H3H2
S9S4S8STSJ
C4H7D5S6H3
S6H6C5DQC6
S6HQC5DQC6
S6H4C5DQC6
SJSQSKSAC2
|
Lost_dogです。もうあと出しじゃんけんすぎるんですが、みなさんの知恵と涙を結集して書き上げました。
特に#8152のtaninswさんのコードが綺麗だったので、ベースにさせていただきました。ポーカーの役は特に規則性がないので、こうやってベタ書きするのが分かりやすいですね。。
Sample Input 1
SQSJSASKST D9D7D6D5D8 C2D2S2H3H2 C2D3S2H3H2 S9S4S8STSJ C4H7D5S6H3 S6H6C5DQC6 S6HQC5DQC6 S6H4C5DQC6 SJSQSKSAC2
Sample Output 1
Royal flush Straight flush Four of a kind Full house Flush Straight Three of a kind Two Pair One Pair No Pair
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | import List
main = interact $ unlines.map (hand.readCard).lines
data Card = Card { suit::Char , rank::Int }
readCard :: String -> [Card]
readCard [] = []
readCard (s:r:cs) = Card s r' : readCard cs
where Just r' = r`elemIndex`"0A23456789TJQK"
isRoyal :: [Card] -> Bool
isRoyal = ([]==).(\\[1,10,11,12,13]).map rank
isFlush :: [Card] -> Bool
isFlush = (1==).length.group.map suit
isStraight :: [Card] -> Bool
isStraight cs = (1==) $ length $ group $ zipWith (-) (tail ds) ds
where ds = sort $ map rank cs
groups :: [Card] -> [Int]
groups = sortBy (flip compare).map length.group.sort.map rank
hand :: [Card] -> String
hand cs = hand' (isFlush cs) (isRoyal cs) (isStraight cs) (groups cs)
where hand' True True True _ = "Royal straight flush"
hand' True True _ _ = "Royal flush"
hand' True _ True _ = "Straight flush"
hand' _ _ _ (4:_) = "Four of a kind"
hand' _ _ _ (3:2:_) = "Full house"
hand' True _ _ _ = "Flush"
hand' _ _ True _ = "Straight"
hand' _ True _ _ = "Straight"
hand' _ _ _ (3:_) = "Three of a kind"
hand' _ _ _ (2:2:_) = "Two Pair"
hand' _ _ _ (2:_) = "One Pair"
hand' _ _ _ _ = "No Pair"
|






xsd
#4978()
Rating6/10=0.60
引数に手札を与えると、ポーカーの役を表示するプログラムを作ってください。
条件:
実行例:
see: ポーカー - Wikipedia
1 reply [ reply ]