概要
- よ一ど ♀(@yo_do_53)さんが、診断メーカーで「大石泉すき」診断を作る
- 「大石泉すき」の5種類の文字から重複順列がランダムに取り出される
- 「大石泉すき」と並ぶ確率は
1 / (5 ** 5) = 1 / 3125
- 桜花(@ikmesyk3)さんが、↑の並びをポーカーに見立てた「大石泉すきポーカー」を提案
- 私が、その役判定プログラムを書く ←New!
先にソースコードを載せておきます
import itertools
import collections
from typing import List
def judge_hand(name : str) -> str:
"""手役を判定する
Parameters
----------
name : str
「大石泉すき」から重複を許して5文字取って並べたもの
Returns
-------
str
判定された役
"""
# 各文字をバラす
name_char = list(name)
# 各文字の出現回数を数え、出現回数部分だけ抽出したもの。
# 例:「大大すすき」→[2, 2, 1]
char_count = collections.Counter(name_char).values()
# 手役の判定処理
if name == '大石泉すき':
# 説明不要
return 'ロイヤルストレートフラッシュ'
elif len(set(name_char)) == 1:
# uniq処理を施して1つしか残らない=ファイブカード
return 'ファイブカード'
elif 4 in char_count:
# ある文字が4つある=フォーカード
return 'フォーカード'
elif len(char_count) == 5:
# 5種類ある=元の文字列が5文字なので各文字ある=ストレートフラッシュ
return 'ストレートフラッシュ'
elif 2 in char_count and 3 in char_count:
# 出現回数に「2」と「3」がある=フルハウス
return 'フルハウス'
elif 'すき' in name:
# すき
return 'すき'
elif 3 in char_count:
# 出現回数に「3」がある=スリーカード
return 'スリーカード'
elif 2 in char_count and len(char_count) == 3:
# 出現回数が3文字分あって「2」が含まれる=消去法からツーペア
return 'ツーペア'
return 'ブタ'
# メインルーチン
if __name__ == '__main__':
# 使用する文字の種類
chars = '大石泉すき'
# itertools.productを利用して、重複順列を作り出し、1セットづつname_charに取り出す
for name_char in itertools.product(chars, repeat=5):
# name_charの全文字を結合したものをnameとする
name = ''.join(name_char)
# 判定を行い、結果を表示する
print(f"{name} {judge_hand(name)}")
result1.txt
大大大大大 ファイブカード
大大大大石 フォーカード
大大大大泉 フォーカード
(中略)
大石泉すす ブタ
大石泉すき ロイヤルストレートフラッシュ
大石泉き大 ブタ
(中略)
きききき泉 フォーカード
ききききす フォーカード
ききききき ファイブカード
ポイント
- 文字列(
str
型)に対してlist()
を適用すると、1文字づつにバラけます- 例:
list('大石泉すき') # => ['大', '石', '泉', 'す', 'き']
- 例:
-
collections.Counter()
を使えば、配列の各要素における個数を数えられます- 例:
[0, 1, 1, 2, 2, 2, 3] # => {0 => 1, 1 => 2, 2 => 3, 3 => 1}
- 例:
-
set()
を使えば重複した文字を実質取り除けます。リストに戻したければlist()
で更に囲みます- 例:
set([0, 1, 1, 2, 2, 2, 3]) # => {0, 1, 2, 3}
- 例:
-
itertools.product()
を使えば、重複順列を自動で生成してくれます- 本来
itertools.product([0, 1, 2], repeat=5)
のように使いますが、Pythonはstr
型もイテレーション可能なので……
- 本来
おまけ:確率を計算
後ろの部分をちょいちょいと書き換えるだけでOKです。
if __name__ == '__main__':
# 使用する文字の種類
chars = '大石泉すき'
# itertools.productを利用して、重複順列を作り出し、1セットづつname_charに取り出す
temp = []
for name_char in itertools.product(chars, repeat=5):
# name_charの全文字を結合したものをnameとする
name = ''.join(name_char)
# 判定を行い、結果を格納する
temp.append(judge_hand(name))
# カウントした結果を表示する
from pprint import pprint
pprint(collections.Counter(temp))
result2.txt
Counter({'ブタ': 984,
'ツーペア': 765,
'スリーカード': 516,
'すき': 435,
'フルハウス': 200,
'ストレートフラッシュ': 119,
'フォーカード': 100,
'ファイブカード': 5,
'ロイヤルストレートフラッシュ': 1})