「ババ抜き」の勝率を相手の3倍にする方法 - くいなちゃんノート
https://pbs.twimg.com/media/FijMP78VQAAZ4Jh.jpg
均等な枚数の手札を配って始めるので、勝つ確率は全員同じように思えますが、実は「誰から配り始めるか」によって勝率が大きく変わることに気付きましたので本記事にまとめておきます。 ポイントは、計53枚のカードの53という数は素数なので、53人で遊ばない限り手札の枚数に差ができることを利用します。
こんな感じのコードを書いてシミュレーションしてみた(雑)
code: script.py
import random
import logging
from collections import Counter
from tqdm import trange
# logging.basicConfig(level=logging.DEBUG, format="%(levelname)s: %(message)s")
class OldMaid():
"""OldMaid game class."""
# cards = list("A234567890JQK"*4 + "X")
def __init__(self) -> None:
self.cards = list("A234567890JQK"*4 + "X")
def get_next_player(self, n_members: int, now_id: int, agari: listbool) -> int: """Get next player id."""
increment = 1
increment += 1
return (now_id + increment) % n_members
def get_next_hands(self, hands: list):
"""Update hands after a turn."""
next_hands = []
for hand in hands:
next_hand = []
ch = Counter(hand)
for card, count in ch.items():
if count % 2 == 1:
next_hand.append(card)
next_hands.append(next_hand)
return next_hands
def get_next_hand(self, hand: listint): """Update hands after a turn."""
next_hand = []
ch = Counter(hand)
for card, count in ch.items():
if count % 2 == 1:
next_hand.append(card)
return next_hand
def play(self, n_members: int) -> tupleint, int: """Play a game of OldMaid with n_members members."""
# Setup
agari = False * n_members # アガリフラグ random.shuffle(self.cards)
logging.debug("Initial cards")
hands = self.get_next_hands(hands) # 最初のペア消去
for i, hand in enumerate(hands):
if len(hand) == 0:
logging.debug(f"Player {i} won.")
logging.debug("Setup complete.")
logging.debug(f"Hands: {hands}\n")
turn = 0
random_id = random.randint(0, n_members - 1)
first_taker_id = self.get_next_player(n_members, random_id, agari) # 最初にカードを引く人
taker_id = first_taker_id
# Play: 誰かの手札の枚数が0になるまで
turn += 1
logging.debug(f"Turn {turn}.")
logging.debug(f"Hands: {hands}")
logging.debug(f"agari flag: {agari}")
# カードの移動
giver_id = self.get_next_player(n_members, taker_id, agari)
c = random.choice(handsgiver_id) # giver_id からランダムにカードを取る logging.debug(f"Player {taker_id} took {c} from Player {giver_id}.\n")
# ペアの消去
# hands = self.get_next_hands(hands)
for i, hand in enumerate(hands):
if len(hand) == 0:
logging.debug(f"Player {i} won.")
taker_id = self.get_next_player(n_members, taker_id, agari)
return first_taker_id, loser
def simulate(n_members: int, n_iter: int) -> list[listint]: """Simulate n_iter games of OldMaid with n_members members."""
om = OldMaid()
cards = list("A234567890JQK"*4 + "X")
print(f"Playing {n_iter} games with {n_members} members.")
print(
f"initial state (number of cards) (dealt in order, starting with the person with the number 0): {[len(cardsi::n_members) for i in range(n_members)]}") print()
for _ in trange(n_iter):
first_taker_id, loser = om.play(n_members)
return res
def main():
n_members = 3
n_iter = 1000000
print(f"\n\nババ抜きシミュレーション")
print(f"0から順にカードを配り、0が1からカードを引き、...という設定で実施する。\n")
res = simulate(n_members, n_iter)
for i in range(len(res)):
# 行ごとに合計で割って、割合を算出
print(f"{i}が最初にカードを引く: ", [(resij / sum(resi)) * 100 for j in range(len(resi))]) if __name__ == "__main__":
main()
https://gyazo.com/1baee1d9e09184d686ef9fa57f509875
https://gyazo.com/0cb12675da72a82f81c4ccafaa6d0085
taikisato.icon もっと直感的に入力したら負ける確率が返ってくるGUIほしい
2022/11/29