次にポーカーの件ですが、まず最初に、
>カード重複を弾くにしても、プログラム上全通り検証する事になるので、
これがちょっと気になるのですが、これは
「最初に、カードが重複しているかどうかをチェックし、
重複していたら『ありえないケース』としてスキップするつもり」ということですか?
それとも「重複するケースもあり得る」ということですか?
後者であればかなり話は厄介になりますが、以下、
「カードの重複はありえない」ことを前提に話を進めます。
52枚のカードから5枚を選んだ時の順列の数は311,875,200ですが、
1つの組み合わせにつき5×4×3×2×1=120通りの順列が存在するので、
組み合わせの数は311,875,200÷120=2,598,960となり、
このおよそ260万種類についてだけ検証すれば良いということになります。
以下、やってみました。
私の環境だと7秒くらいでした。
#define repeat2(%1,%2) repeat (%2)-(%1)+1,%1 //cntの初期値が%1、最終値が%2になるrepeat
//以下、次のようにルールを決める。
//・52枚のカードには0〜51の通し番号を振る。
//・通し番号を13で割った余りがカードの数字(0なら"A"、1なら"2"…12なら"K")
//・通し番号を13で割った結果がカードのスート(0がスペード、1がクラブ、2がハート、3がダイヤ)
#module
#define ctype rank(%1) ((%1)\13)
#define ctype suit(%1) ((%1)/13)
//por_hand(p1)
//p1は要素数5の整数変数で、それぞれに0〜51のカード番号を入れる。
//ポーカーの手役の判定を行い、その結果を以下のように返す
// 0:ノーペア 1:ワンペア 2:ツーペア 3:スリーカード 4:ストレート
// 5:フラッシュ 6:フルハウス 7:フォーカード 8:ストレートフラッシュ 9:ロイヤルフラッシュ
#defcfunc por_hand array hand
//フラッシュ判定
f_flag=1 //フラッシュフラグ
x=suit(hand(0))
repeat 4,1
if suit(hand(cnt))!=x : f_flag=0 : break
loop
//以下、スートは判定に関係なくなるので、数字だけを基準に処理を行う
dim ranks,5
repeat 5 : ranks(cnt)=rank(hand(cnt)) : loop
sortval ranks,0 //ranksを小さい順にソート。この結果、同じ数字は隣接することになる。
//ストレート判定
s_flag=1 //ストレートフラグ
x=ranks(0)
repeat 4,1
if ranks(cnt)!=x+cnt : s_flag=0 : break
loop
if s_flag {
//ストレートが成立した場合
if f_flag : return 8 //フラッシュが同時成立した場合はストレートフラッシュ
return 4 //そうでない場合はストレート
}
//ロイヤルストレート(10・J・Q・K・Aの特殊ストレート)判定
if (ranks(0)=0) & (ranks(1)=9) & (ranks(2)=10) & (ranks(3)=11) & (ranks(4)=12) {
if f_flag : return 9 //フラッシュが同時成立した場合はロイヤルフラッシュ
return 4 //そうでない場合はストレート
}
if f_flag : return 5 //フラッシュ
//この時点で残る可能性は、ノーペア、ワンペア、ツーペア、スリーカード、フルハウス、フォーカード
dim pairs,4 //隣接しているカード同士が同じ数字かどうか
pair_num=0 //その数
repeat 4
if ranks(cnt)=ranks(cnt+1) {
pairs(cnt)=1
pair_num++
}
loop
switch pair_num
case 1
return 1 //ペアが1つだけならワンペア
swbreak
case 2
//隣接カード同士のペアが2つの場合、スリーカードかツーペア
if (pairs(0)&pairs(1)) | (pairs(1)&pairs(2)) | (pairs(2)&pairs(3)) : return 3
return 2
swbreak
case 3
//隣接カード同士のペアが3つの場合、フォーカードかフルハウス
if (pairs(0)=0) | (pairs(3)=0) : return 7 //ペアが左か右に寄っていたらフォーカード
return 6 //そうでなければフルハウス
swbreak
swend
return 0
#global
#include "winmm.as"
TimeGetTime : s=stat
dim res,10
dim hand,5
x=0
repeat2 0,47
hand(0)=cnt
repeat2 hand(0)+1,48
hand(1)=cnt
repeat2 hand(1)+1,49
hand(2)=cnt
repeat2 hand(2)+1,50
hand(3)=cnt
repeat2 hand(3)+1,51
hand(4)=cnt
res(por_hand(hand))++
x++
loop
loop
loop
loop
loop
TimeGetTime : s=stat-s
//結果表示
sdim text,64,10
text="ノーペア","ワンペア","ツーペア","スリーカード","ストレート","フラッシュ","フルハウス","フォーカード"
text(8)="ストレートフラッシュ","ロイヤルフラッシュ"
mes "組み合わせ総数:"+str(x)
repeat 10
mes text(cnt)+":"+str(res(cnt))
loop
mes "\n順列総数:"+str(x*120)
repeat 10
mes text(cnt)+":"+str(res(cnt)*120)
loop
mes "\n処理にかかった時間:"+str(s)+"ミリ秒"
念のためWikipediaの「ポーカー・ハンドの一覧」を確認してみましたが、
正しく計算できたことが確認できました。
https://ja.wikipedia.org/wiki/%E3%83%9D%E3%83%BC%E3%82%AB%E3%83%BC%E3%83%BB%E3%83%8F%E3%83%B3%E3%83%89%E3%81%AE%E4%B8%80%E8%A6%A7