Skip to content

Instantly share code, notes, and snippets.

@YSRKEN
Last active December 9, 2018 04:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save YSRKEN/fe4e105f3b9e9e66e525d21404de0e93 to your computer and use it in GitHub Desktop.
Save YSRKEN/fe4e105f3b9e9e66e525d21404de0e93 to your computer and use it in GitHub Desktop.
地上最速の「大石泉すき」判定コードを書いてみた ref: https://qiita.com/YSRKEN/items/2f1603df95af3dc00ef6
#include <iostream>
#include <chrono>
using namespace std;
using namespace std::chrono;
const size_t LOOP_COUNT = 10000;
int judge_hand(const int digit[]) {
// ロイヤルストレートフラッシュ
if (digit[0] == 0 && digit[1] == 1 && digit[2] == 2 && digit[3] == 3 && digit[4] == 4)
return 0;
// ファイブカード
if (digit[0] == digit[1] && digit[1] == digit[2] && digit[2] == digit[3] && digit[3] == digit[4])
return 1;
// フォーカード
int count[] = {0, 0, 0, 0, 0};
for (int i = 0; i < 5; ++i){
++count[digit[i]];
}
for (int i = 0; i < 5; ++i){
if (count[i] == 4)
return 2;
}
// ストレートフラッシュ
bool flg = true;
for (int i = 0; i < 5; ++i){
if (count[i] == 0) {
flg = false;
break;
}
}
if (flg) {
return 3;
}
// フルハウス
bool flg_2 = false;
bool flg_3 = false;
for (int i = 0; i < 5; ++i){
if (count[i] == 2) {
flg_2 = true;
continue;
}
if (count[i] == 3) {
flg_3 = true;
continue;
}
}
if (flg_2 && flg_3) {
return 4;
}
// すき
if (digit[0] == 3 && digit[1] == 4)
return 5;
if (digit[1] == 3 && digit[2] == 4)
return 5;
if (digit[2] == 3 && digit[3] == 4)
return 5;
if (digit[3] == 3 && digit[4] == 4)
return 5;
// スリーカード
if (flg_3) {
return 6;
}
// ツーペア
if (flg_2) {
int digit_count = 0;
for (int i = 0; i < 5; ++i){
if (count[i] != 0) {
++digit_count;
}
}
if (digit_count == 3) {
return 7;
}
}
return 99;
}
int main()
{
cout << "ループ回数:" << LOOP_COUNT << "回" << endl;
auto start = system_clock::now();
volatile int result = 99;
int digit[] = {0, 0, 0, 0, 0};
for (size_t n = 0; n < LOOP_COUNT; ++n) {
for (size_t i1 = 0; i1 < 5; ++i1){
digit[0] = i1;
for (size_t i2 = 0; i2 < 5; ++i2){
digit[1] = i2;
for (size_t i3 = 0; i3 < 5; ++i3){
digit[2] = i3;
for (size_t i4 = 0; i4 < 5; ++i4){
digit[3] = i4;
for (size_t i5 = 0; i5 < 5; ++i5){
digit[4] = i5;
result = 99;
}}}}}
}
auto dur = system_clock::now() - start;
auto nanosec = std::chrono::duration_cast<std::chrono::nanoseconds>(dur).count();
cout << "ループ自体の時間:" << nanosec << "ナノ秒(" << (1.0 * nanosec / LOOP_COUNT / 5 / 5 / 5 / 5 / 5) << "ナノ秒/回)" << endl;
start = system_clock::now();
for (size_t n = 0; n < LOOP_COUNT; ++n) {
for (size_t i1 = 0; i1 < 5; ++i1){
digit[0] = i1;
for (size_t i2 = 0; i2 < 5; ++i2){
digit[1] = i2;
for (size_t i3 = 0; i3 < 5; ++i3){
digit[2] = i3;
for (size_t i4 = 0; i4 < 5; ++i4){
digit[3] = i4;
for (size_t i5 = 0; i5 < 5; ++i5){
digit[4] = i5;
result = judge_hand(digit);
}}}}}
}
dur = system_clock::now() - start;
auto nanosec2 = std::chrono::duration_cast<std::chrono::nanoseconds>(dur).count() - nanosec;
cout << "計算時間:" << nanosec2 << "ナノ秒(" << (1.0 * nanosec2 / LOOP_COUNT / 5 / 5 / 5 / 5 / 5) << "ナノ秒/回)" << endl;
}
int judge_hand_fast(volatile int digit[]) {
// 各数字の出現回数
int count[] = {0, 0, 0, 0, 0};
for (int i = 0; i < 5; ++i)
++count[digit[i]];
// 出現回数の出現回数
int count2[] = {0, 0, 0, 0, 0, 0};
for (int i = 0; i < 5; ++i)
++count2[count[i]];
// 判定
if (count2[1] == 5) {
if (digit[0] == 0 && digit[1] == 1 && digit[2] == 2 && digit[3] == 3 && digit[4] == 4)
// ロイヤルストレートフラッシュ
return 0;
else
// ストレートフラッシュ
return 3;
}
// ファイブカード
if (count2[5] == 1)
return 1;
// フォーカード
if (count2[4] == 1)
return 2;
// フルハウス
if (count2[3] == 1 && count2[2] == 1)
return 4;
// すき
if (digit[0] == 3 && digit[1] == 4)
return 5;
if (digit[1] == 3 && digit[2] == 4)
return 5;
if (digit[2] == 3 && digit[3] == 4)
return 5;
if (digit[3] == 3 && digit[4] == 4)
return 5;
// スリーカード
if (count2[3] == 1)
return 6;
if (count2[2] == 2)
return 7;
return 99;
}
int judge_hand_fast2(volatile int digit[]) {
// 各数字の出現回数
int count[] = {0, 0, 0, 0, 0};
for (int i = 0; i < 5; ++i)
++count[digit[i]];
// 出現回数の出現回数
int count2[] = {0, 0, 0, 0, 0, 0};
for (int i = 0; i < 5; ++i)
++count2[count[i]];
// 判定
// ツーペア・すき
if (count2[2] == 2){
// すき
if (digit[0] == 3 && digit[1] == 4)
return 5;
if (digit[1] == 3 && digit[2] == 4)
return 5;
if (digit[2] == 3 && digit[3] == 4)
return 5;
if (digit[3] == 3 && digit[4] == 4)
return 5;
// ツーペア
return 7;
}
// スリーカード・すき・フルハウス
if (count2[3] == 1){
// すき
bool sukiFlg = false;
if (digit[0] == 3 && digit[1] == 4)
sukiFlg = true;
else if (digit[1] == 3 && digit[2] == 4)
sukiFlg = true;
else if (digit[2] == 3 && digit[3] == 4)
sukiFlg = true;
else if (digit[3] == 3 && digit[4] == 4)
sukiFlg = true;
// フルハウス
if (count2[2] == 1)
return 4;
if (sukiFlg)
return 5;
// スリーカード
return 6;
}
// すき
bool sukiFlg = false;
if (digit[0] == 3 && digit[1] == 4)
sukiFlg = true;
else if (digit[1] == 3 && digit[2] == 4)
sukiFlg = true;
else if (digit[2] == 3 && digit[3] == 4)
sukiFlg = true;
else if (digit[3] == 3 && digit[4] == 4)
sukiFlg = true;
// ストレートフラッシュ・ロイヤルストレートフラッシュ
if (count2[1] == 5) {
if (digit[0] == 0 && digit[1] == 1 && digit[2] == 2 && digit[3] == 3 && digit[4] == 4)
// ロイヤルストレートフラッシュ
return 0;
else
// ストレートフラッシュ
return 3;
}
// フォーカード
if (count2[4] == 1)
return 2;
// ファイブカード
if (count2[5] == 1)
return 1;
if (sukiFlg)
return 5;
return 99;
}
int cache[3125] = {};
// 判定用関数
int judge_hand_fast3(const int digit[]) {
return cache[digit[0]*5*5*5*5+digit[1]*5*5*5+digit[2]*5*5+digit[3]*5+digit[4]];
}
// 使用前の初期化
for (size_t i1 = 0; i1 < 5; ++i1){
digit[0] = i1;
for (size_t i2 = 0; i2 < 5; ++i2){
digit[1] = i2;
for (size_t i3 = 0; i3 < 5; ++i3){
digit[2] = i3;
for (size_t i4 = 0; i4 < 5; ++i4){
digit[3] = i4;
for (size_t i5 = 0; i5 < 5; ++i5){
digit[4] = i5;
cache[i1*5*5*5*5+i2*5*5*5+i3*5*5+i4*5+i5] = judge_hand(digit);
}}}}}
inline uint32_t calc_bitboard(const int index){
return 1 << (index * 3);
}
int judge_hand_fast4(const int digit[]) {
// 各数字の出現回数をビットボードを利用してカウント
uint32_t count_board = 0;
count_board += calc_bitboard(digit[0]);
count_board += calc_bitboard(digit[1]);
count_board += calc_bitboard(digit[2]);
count_board += calc_bitboard(digit[3]);
count_board += calc_bitboard(digit[4]);
const int count_0 = count_board & 0x7;
const int count_1 = (count_board >> 3) & 0x7;
const int count_2 = (count_board >> 6) & 0x7;
const int count_3 = (count_board >> 9) & 0x7;
const int count_4 = (count_board >> 12) & 0x7;
// 各数字の出現回数の出現回数をビットボードを利用してカウント
count_board = 0;
count_board += calc_bitboard(count_0);
count_board += calc_bitboard(count_1);
count_board += calc_bitboard(count_2);
count_board += calc_bitboard(count_3);
count_board += calc_bitboard(count_4);
const int count2_0 = count_board & 0x7;
const int count2_1 = (count_board >> 3) & 0x7;
const int count2_2 = (count_board >> 6) & 0x7;
const int count2_3 = (count_board >> 9) & 0x7;
const int count2_4 = (count_board >> 12) & 0x7;
const int count2_5 = (count_board >> 15) & 0x7;
// 判定
// ツーペア・すき
if (count2_2 == 2){
// すき
if (digit[0] == 3 && digit[1] == 4)
return 5;
if (digit[1] == 3 && digit[2] == 4)
return 5;
if (digit[2] == 3 && digit[3] == 4)
return 5;
if (digit[3] == 3 && digit[4] == 4)
return 5;
// ツーペア
return 7;
}
// スリーカード・すき・フルハウス
if (count2_3 == 1){
// フルハウス
if (count2_2 == 1)
return 4;
// すき
bool sukiFlg = false;
if (digit[0] == 3 && digit[1] == 4)
return 5;
else if (digit[1] == 3 && digit[2] == 4)
return 5;
else if (digit[2] == 3 && digit[3] == 4)
return 5;
else if (digit[3] == 3 && digit[4] == 4)
return 5;
// スリーカード
return 6;
}
// ストレートフラッシュ・ロイヤルストレートフラッシュ
if (count2_1 == 5) {
if (digit[0] == 0 && digit[1] == 1 && digit[2] == 2 && digit[3] == 3 && digit[4] == 4)
// ロイヤルストレートフラッシュ
return 0;
else
// ストレートフラッシュ
return 3;
}
// フォーカード
if (count2_4 == 1)
return 2;
// ファイブカード
if (count2_5 == 1)
return 1;
// すき
if (digit[0] == 3 && digit[1] == 4)
return 5;
else if (digit[1] == 3 && digit[2] == 4)
return 5;
else if (digit[2] == 3 && digit[3] == 4)
return 5;
else if (digit[3] == 3 && digit[4] == 4)
return 5;
return 99;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment