Harigami
ログイン
anonymous タイトルなし
No License Python
コピー
from collections import defaultdict
from enum import Enum
from itertools import chain
import random
from typing import Iterable, Iterator, List, Union

Card = Union["NormalCard", "Jorker"]


class Suit(Enum):
    HEART = 0
    CLAB = 1
    DIA = 2
    SPADE = 3

    @classmethod
    def display(cls, suit):
        return {cls.HEART: "❤️", cls.CLAB: "♣️", cls.DIA: "♦️", cls.SPADE: "♠️"}[suit]

    def __repr__(self):
        return f"{self.display(self)}"


class Rank(Enum):
    THREE = 3
    FOUR = 4
    FIVE = 5
    SIX = 6
    SEVEN = 7
    EIGHT = 8
    NINE = 9
    TEN = 10
    JACK = 11
    QUEEN = 12
    KING = 13
    ACE = 14
    DEUCE = 15

    @classmethod
    def display(cls, suit):
        dic = {
            cls.TEN: "T",
            cls.JACK: "J️",
            cls.QUEEN: "Q",
            cls.KING: "K",
            cls.ACE: "A",
            cls.DEUCE: "2",
        }
        if suit in dic:
            return dic[suit]
        return str(suit.value)

    def __repr__(self):
        return f"{self.display(self)}"


class NormalCard:
    def __init__(self, rank, suit):
        self.rank = rank
        self.suit = suit

    def __repr__(self):
        return f"{repr(self.rank)}{repr(self.suit)}"

    def __gt__(self, other):
        if self.rank.value > other.rank.value:
            return True
        elif self.rank.value < other.rank.value:
            return False
        return self.suit.value > other.suit.value

    def __hash__(self):
        return hash(repr(self))


class Jorker:
    def __repr__(self):
        return "Jo"

    def __hash__(self):
        return hash(repr(self))


class Deck:
    JORKER_NUM = 2
    normal_cards: List[Card] = [
        NormalCard(rank, suit) for rank in Rank for suit in Suit
    ]
    jorkers: List[Card] = [Jorker()] * JORKER_NUM
    cards = normal_cards + jorkers

    def __init__(self, jorker_num=2):
        random.shuffle(self.cards)
        self.it_cards = iter(self.cards)

    def deal(self, amount: int) -> Iterator[Card]:
        for _ in range(amount):
            yield next(self.it_cards)

    def reset(self, jorker_num=2):
        self.__init__(jorker_num)

    @classmethod
    def choices(cls, amount: int) -> List[Card]:
        return random.choices(cls.cards, k=amount)


def divide_cards(cards: List[Card]):
    normel_cards: List[NormalCard] = [
        card for card in cards if isinstance(card, NormalCard)
    ]
    jorkers: List[Jorker] = [card for card in cards if isinstance(card, Jorker)]
    return normel_cards, jorkers


class Hand:
    def __init__(self, cards: Iterable[Card]):
        self.normal_cards, self.jorkers = divide_cards(list(cards))
        self.normal_cards.sort()
        self.sorted_cards = self.normal_cards + self.jorkers

    def get_duplicates(self):
        rank_to_cards = defaultdict(list)
        for normal_card in self.normal_cards:
            rank_to_cards[normal_card.rank].append(normal_card)
        for rank in rank_to_cards.keys():
            rank_to_cards[rank].extend(self.jorkers)
        return [cards for (rank, cards) in rank_to_cards.items() if len(cards) >= 2]

    def get_sequences(self):
        suit_to_cards = {}
        for suit in Suit:
            same_suit_cards = [card for card in self.normal_cards if card.suit is suit]
            suit_to_cards[suit] = get_consectives(same_suit_cards, len(self.jorkers))
        sequences = list(chain.from_iterable(suit_to_cards.values()))
        return sorted(sequences, key=lambda seq: seq[0].rank.value)


def get_consectives(same_suit_cards: List[NormalCard], jorker_num: int):
    seqs = []
    for i, _ in enumerate(same_suit_cards):
        seq = get_seq(same_suit_cards[i:], jorker_num)
        if len(seq) >= 3:
            seqs.append(seq)
    return seqs


def get_seq(cards: List[NormalCard], jorker_num: int) -> List[Card]:
    """先頭から始まる最長のsequenceを返す"""
    ret: List[Card] = [cards[0]]
    for i, current_card in enumerate(cards[:-1]):
        next_card = cards[i + 1]
        delta = next_card.rank.value - current_card.rank.value
        if delta == 1:
            ret.append(next_card)
        elif delta == 2 and jorker_num >= 1:
            jorker_num -= 1
            ret.append(Jorker())
            ret.append(next_card)
        elif delta == 3 and jorker_num >= 2:
            jorker_num -= 2
            ret.extend([Jorker(), Jorker()])
            ret.append(next_card)
        else:
            break
        i += 1
    for _ in range(jorker_num):
        ret.append(Jorker())
    return ret


def get_max_length(arrays):
    if arrays:
        return max(map(lambda x: len(x), arrays))
    return 0


if __name__ == "__main__":
    result = {"deps": defaultdict(int), "seqs": defaultdict(int)}
    trial = 100
    for _ in range(trial):
        hand = Hand(Deck.choices(7))
        deps = hand.get_duplicates()
        seqs = hand.get_sequences()
        result["deps"][get_max_length(deps)] += 1
        result["seqs"][get_max_length(seqs)] += 1
    print(result)
from collections import defaultdict
from enum import Enum
from itertools import chain
import random
from typing import Iterable, Iterator, List, Union

Card = Union["NormalCard", "Jorker"]


class Suit(Enum):
    HEART = 0
    CLAB = 1
    DIA = 2
    SPADE = 3

    @classmethod
    def display(cls, suit):
        return {cls.HEART: "❤️", cls.CLAB: "♣️", cls.DIA: "♦️", cls.SPADE: "♠️"}[suit]

    def __repr__(self):
        return f"{self.display(self)}"


class Rank(Enum):
    THREE = 3
    FOUR = 4
    FIVE = 5
    SIX = 6
    SEVEN = 7
    EIGHT = 8
    NINE = 9
    TEN = 10
    JACK = 11
    QUEEN = 12
    KING = 13
    ACE = 14
    DEUCE = 15

    @classmethod
    def display(cls, suit):
        dic = {
            cls.TEN: "T",
            cls.JACK: "J️",
            cls.QUEEN: "Q",
            cls.KING: "K",
            cls.ACE: "A",
            cls.DEUCE: "2",
        }
        if suit in dic:
            return dic[suit]
        return str(suit.value)

    def __repr__(self):
        return f"{self.display(self)}"


class NormalCard:
    def __init__(self, rank, suit):
        self.rank = rank
        self.suit = suit

    def __repr__(self):
        return f"{repr(self.rank)}{repr(self.suit)}"

    def __gt__(self, other):
        if self.rank.value > other.rank.value:
            return True
        elif self.rank.value < other.rank.value:
            return False
        return self.suit.value > other.suit.value

    def __hash__(self):
        return hash(repr(self))


class Jorker:
    def __repr__(self):
        return "Jo"

    def __hash__(self):
        return hash(repr(self))


class Deck:
    JORKER_NUM = 2
    normal_cards: List[Card] = [
        NormalCard(rank, suit) for rank in Rank for suit in Suit
    ]
    jorkers: List[Card] = [Jorker()] * JORKER_NUM
    cards = normal_cards + jorkers

    def __init__(self, jorker_num=2):
        random.shuffle(self.cards)
        self.it_cards = iter(self.cards)

    def deal(self, amount: int) -> Iterator[Card]:
        for _ in range(amount):
            yield next(self.it_cards)

    def reset(self, jorker_num=2):
        self.__init__(jorker_num)

    @classmethod
    def choices(cls, amount: int) -> List[Card]:
        return random.choices(cls.cards, k=amount)


def divide_cards(cards: List[Card]):
    normel_cards: List[NormalCard] = [
        card for card in cards if isinstance(card, NormalCard)
    ]
    jorkers: List[Jorker] = [card for card in cards if isinstance(card, Jorker)]
    return normel_cards, jorkers


class Hand:
    def __init__(self, cards: Iterable[Card]):
        self.normal_cards, self.jorkers = divide_cards(list(cards))
        self.normal_cards.sort()
        self.sorted_cards = self.normal_cards + self.jorkers

    def get_duplicates(self):
        rank_to_cards = defaultdict(list)
        for normal_card in self.normal_cards:
            rank_to_cards[normal_card.rank].append(normal_card)
        for rank in rank_to_cards.keys():
            rank_to_cards[rank].extend(self.jorkers)
        return [cards for (rank, cards) in rank_to_cards.items() if len(cards) >= 2]

    def get_sequences(self):
        suit_to_cards = {}
        for suit in Suit:
            same_suit_cards = [card for card in self.normal_cards if card.suit is suit]
            suit_to_cards[suit] = get_consectives(same_suit_cards, len(self.jorkers))
        sequences = list(chain.from_iterable(suit_to_cards.values()))
        return sorted(sequences, key=lambda seq: seq[0].rank.value)


def get_consectives(same_suit_cards: List[NormalCard], jorker_num: int):
    seqs = []
    for i, _ in enumerate(same_suit_cards):
        seq = get_seq(same_suit_cards[i:], jorker_num)
        if len(seq) >= 3:
            seqs.append(seq)
    return seqs


def get_seq(cards: List[NormalCard], jorker_num: int) -> List[Card]:
    """先頭から始まる最長のsequenceを返す"""
    ret: List[Card] = [cards[0]]
    for i, current_card in enumerate(cards[:-1]):
        next_card = cards[i + 1]
        delta = next_card.rank.value - current_card.rank.value
        if delta == 1:
            ret.append(next_card)
        elif delta == 2 and jorker_num >= 1:
            jorker_num -= 1
            ret.append(Jorker())
            ret.append(next_card)
        elif delta == 3 and jorker_num >= 2:
            jorker_num -= 2
            ret.extend([Jorker(), Jorker()])
            ret.append(next_card)
        else:
            break
        i += 1
    for _ in range(jorker_num):
        ret.append(Jorker())
    return ret


def get_max_length(arrays):
    if arrays:
        return max(map(lambda x: len(x), arrays))
    return 0


if __name__ == "__main__":
    result = {"deps": defaultdict(int), "seqs": defaultdict(int)}
    trial = 100
    for _ in range(trial):
        hand = Hand(Deck.choices(7))
        deps = hand.get_duplicates()
        seqs = hand.get_sequences()
        result["deps"][get_max_length(deps)] += 1
        result["seqs"][get_max_length(seqs)] += 1
    print(result)
コンソール
現在、コメントはありません。
最初のコメンターになりませんか?