





'''simple docstring'''

from __future__ import annotations

import os






class      UpperCAmelCase			:
 __lowercase     	=       (
     """High card""",
     """One pair""",
     """Two pairs""",
     """Three of a kind""",
     """Straight""",
     """Flush""",
     """Full house""",
     """Four of a kind""",
     """Straight flush""",
     """Royal flush""",
 )

 __lowercase     	=       (
     """""",  # placeholder as tuples are zero-indexed
     """One""",
     """Two""",
     """Three""",
     """Four""",
     """Five""",
     """Six""",
     """Seven""",
     """Eight""",
     """Nine""",
     """Ten""",
     """Jack""",
     """Queen""",
     """King""",
     """Ace""",
 )
 def __init__(       self   :int		, lowercase_   :str							)->							None:
     if not isinstance(lowercase_		, lowercase_							):
         A__       =    F"Hand should be of type 'str': {hand!r}"
         raise TypeError(lowercase_							)
     # split removes duplicate whitespaces so no need of strip
     if len(hand.split(" "							)							) != 5:
         A__       =    F"Hand should contain only 5 cards: {hand!r}"
         raise ValueError(lowercase_							)
     A__       =    hand
     A__       =    0
     A__       =    0
     A__,			A__       =    self._internal_state()
     A__       =    self._get_hand_type()
     A__       =    self._card_values[0]
 @property
 def   UpperCAmelCase_							(       self   :str							)->							Tuple:
     return self._hand
 def   UpperCAmelCase_							(       self   :Tuple		, lowercase_   :PokerHand							)->							str:
     # Breaking the tie works on the following order of precedence:
     # 1. First pair (default 0)
     # 2. Second pair (default 0)
     # 3. Compare all cards in reverse order because they are sorted.

     # First pair and second pair will only be a non-zero value if the card
     # type is either from the following:
     # 21: Four of a kind
     # 20: Full house
     # 17: Three of a kind
     # 16: Two pairs
     # 15: One pair
     if self._hand_type > other._hand_type:
         return "Win"
     elif self._hand_type < other._hand_type:
         return "Loss"
     elif self._first_pair == other._first_pair:
         if self._second_pair == other._second_pair:
             return self._compare_cards(lowercase_							)
         else:
             return "Win" if self._second_pair > other._second_pair else "Loss"
     return "Win" if self._first_pair > other._first_pair else "Loss"
 def   UpperCAmelCase_							(       self   :Any							)->							str:
     A__       =    PokerHand._HAND_NAME[self._hand_type - 14]
     A__       =    PokerHand._CARD_NAME[self._high_card]
     A__       =    PokerHand._CARD_NAME[self._first_pair]
     A__       =    PokerHand._CARD_NAME[self._second_pair]
     if self._hand_type in [22, 19, 18]:
         return name + F", {high}-high"
     elif self._hand_type in [21, 17, 15]:
         return name + F", {paira}s"
     elif self._hand_type in [20, 16]:
         A__       =    "over" if self._hand_type == 20 else "and"
         return name + F", {paira}s {join} {paira}s"
     elif self._hand_type == 23:
         return name
     else:
         return name + F", {high}"
 def   UpperCAmelCase_							(       self   :Dict		, lowercase_   :PokerHand							)->							str:
     # Enumerate gives us the index as well as the element of a list
     for index, card_value in enumerate(self._card_values							):
         if card_value != other._card_values[index]:
             return "Win" if card_value > other._card_values[index] else "Loss"
     return "Tie"
 def   UpperCAmelCase_							(       self   :List[Any]							)->							int:
     # Number representing the type of hand internally:
     # 23: Royal flush
     # 22: Straight flush
     # 21: Four of a kind
     # 20: Full house
     # 19: Flush
     # 18: Straight
     # 17: Three of a kind
     # 16: Two pairs
     # 15: One pair
     # 14: High card
     if self._is_flush():
         if self._is_five_high_straight() or self._is_straight():
             return 23 if sum(self._card_values							) == 60 else 22
         return 19
     elif self._is_five_high_straight() or self._is_straight():
         return 18
     return 14 + self._is_same_kind()
 def   UpperCAmelCase_							(       self   :str							)->							bool:
     return len(self._card_suit							) == 1
 def   UpperCAmelCase_							(       self   :Optional[int]							)->							bool:
     # If a card is a five high straight (low ace) change the location of
     # ace from the start of the list to the end. Check whether the first
     # element is ace or not. (Don't want to change again)
     # Five high straight (low ace): AH 2H 3S 4C 5D
     # Why use sorted here? One call to this function will mutate the list to
     # [5, 4, 3, 2, 14] and so for subsequent calls (which will be rare) we
     # need to compare the sorted version.
     # Refer test_multiple_calls_five_high_straight in test_poker_hand.py
     if sorted(self._card_values							) == [2, 3, 4, 5, 14]:
         if self._card_values[0] == 14:
             # Remember, our list is sorted in reverse order
             A__       =    self._card_values.pop(0							)
             self._card_values.append(lowercase_							)
         return True
     return False
 def   UpperCAmelCase_							(       self   :Tuple							)->							bool:
     for i in range(4							):
         if self._card_values[i] - self._card_values[i + 1] != 1:
             return False
     return True
 def   UpperCAmelCase_							(       self   :int							)->							int:
     # Kind Values for internal use:
     # 7: Four of a kind
     # 6: Full house
     # 3: Three of a kind
     # 2: Two pairs
     # 1: One pair
     # 0: False
     A__       =    A__       =    A__       =    0
     for i in range(4							):
         # Compare two cards at a time, if they are same increase 'kind',
         # add the value of the card to val1, if it is repeating again we
         # will add 2 to 'kind' as there are now 3 cards with same value.
         # If we get card of different value than val1, we will do the same
         # thing with val2
         if self._card_values[i] == self._card_values[i + 1]:
             if not vala:
                 A__       =    self._card_values[i]
                 kind += 1
             elif vala == self._card_values[i]:
                 kind += 2
             elif not vala:
                 A__       =    self._card_values[i]
                 kind += 1
             elif vala == self._card_values[i]:
                 kind += 2
        # For consistency in hand type (look at note in _get_hand_type function)
     A__       =    kind + 2 if kind in [4, 5] else kind
     # first meaning first pair to compare in 'compare_with'
     A__       =    max(lowercase_		, lowercase_							)
     A__       =    min(lowercase_		, lowercase_							)
     # If it's full house (three count pair + two count pair), make sure
     # first pair is three count and if not then switch them both.
     if kind == 6 and self._card_values.count(lowercase_							) != 3:
         A__,			A__       =    second, first
     A__       =    first
     A__       =    second
     return kind
 def   UpperCAmelCase_							(       self   :Any							)->							tuple[list[int], set[str]]:
     # Internal representation of hand as a list of card values and
     # a set of card suit
     A__       =    {"T": "10", "J": "11", "Q": "12", "K": "13", "A": "14"}
     A__       =    self._hand.translate(str.maketrans(lowercase_							)							).split()
     A__       =    [int(card[:-1]							) for card in new_hand]
     A__       =    {card[-1] for card in new_hand}
     return sorted(lowercase_		, reverse=lowercase_							), card_suit
 def __repr__(       self   :Dict							)->							List[Any]:
     return F"{self.__class__}(\"{self._hand}\")"
 def __str__(       self   :Optional[int]							)->							int:
     return self._hand
 def __eq__(       self   :Any		, lowercase_   :Optional[int]							)->							Optional[Any]:
     if isinstance(lowercase_		, lowercase_							):
         return self.compare_with(lowercase_							) == "Tie"
     return NotImplemented
 def __lt__(       self   :Optional[int]		, lowercase_   :str							)->							List[Any]:
     if isinstance(lowercase_		, lowercase_							):
         return self.compare_with(lowercase_							) == "Loss"
     return NotImplemented
 def __le__(       self   :List[Any]		, lowercase_   :str							)->							Any:
     if isinstance(lowercase_		, lowercase_							):
         return self < other or self == other
     return NotImplemented
 def __gt__(       self   :Optional[Any]		, lowercase_   :Union[str, Any]							)->							List[Any]:
     if isinstance(lowercase_		, lowercase_							):
         return not self < other and self != other
     return NotImplemented
 def __ge__(       self   :Optional[int]		, lowercase_   :Union[str, Any]							)->							Any:
     if isinstance(lowercase_		, lowercase_							):
         return not self < other
     return NotImplemented



 def __hash__(       self   :Optional[int]							)->							int:
     return object.__hash__(self							)





def 		UpperCamelCase       (							):
    # Solution for problem number 54 from Project Euler
    # Input from poker_hands.txt file
    A__       =    0
    A__       =    os.path.abspath(os.path.dirname(_lowerCamelCase ) )
    A__       =    os.path.join(_lowerCamelCase		, "poker_hands.txt" )
    with open(_lowerCamelCase ) as file_hand:
        for line in file_hand:
            A__       =    line[:14].strip()
            A__       =    line[15:].strip()
            A__,			A__       =    PokerHand(_lowerCamelCase ), PokerHand(_lowerCamelCase )
            A__       =    player.compare_with(_lowerCamelCase )
            if output == "Win":
                answer += 1
    return answer


if __name__ == "__main__":
 solution()










'''simple docstring'''

import collections

from .utils import ExplicitEnum, is_torch_available, logging


if is_torch_available():
  import torch


__lowerCAmelCase							:			Optional[int]				=logging.get_logger(__name__)






class      UpperCAmelCase			:
 def __init__(       self   :Optional[int]		, lowercase_   :Any		, lowercase_   :Any=21		, lowercase_   :Any=[]		, lowercase_   :Dict=None							)->							Tuple:
     A__       =    model
     A__       =    trace_batch_nums
     A__       =    abort_after_batch_num

     # keep a LIFO buffer of frames to dump as soon as inf/nan is encountered to give context to the problem emergence
     A__       =    collections.deque([]		, lowercase_							)
     A__       =    []
     A__       =    0
     A__       =    0
     A__       =    False
     A__       =    "                 "

     self.analyse_model()

     self.register_forward_hook()
 def   UpperCAmelCase_							(       self   :Any		, lowercase_   :Any=None							)->							Optional[Any]:
     if frame is not None:
         self.expand_frame(lowercase_							)
     self.frames.append("\n".join(self.frame							)							)
     A__       =    []  # start a new frame
 def   UpperCAmelCase_							(       self   :Union[str, Any]		, lowercase_   :Dict							)->							List[str]:
     self.frame.append(lowercase_							)
 def   UpperCAmelCase_							(       self   :int							)->							Dict:
     print("\n".join(self.frames							)							)
     A__       =    []
 def   UpperCAmelCase_							(       self   :str							)->							Union[str, Any]:
     A__       =    []
 def   UpperCAmelCase_							(       self   :List[str]							)->							Optional[Any]:
     print(F"\nDetected inf/nan during batch_number={self.batch_number}"							)
     print(F"Last {len(self.frames							)} forward frames:"							)
     print(F"{'abs min':8} {'abs max':8} metadata"							)
     print("\n".join(self.frames							)							)
     print("\n\n"							)
     A__       =    []
 def   UpperCAmelCase_							(       self   :Any							)->							Optional[Any]:
     # extract the fully qualified module names, to be able to report at run time. e.g.:
     # encoder.block.2.layer.0.SelfAttention.o
     #
     # for shared weights only the first shared module name will be registered
     A__       =    {m: name for name, m in self.model.named_modules()}
     # self.longest_module_name = max(len(v) for v in self.module_names.values())
 def   UpperCAmelCase_							(       self   :Tuple		, lowercase_   :Dict		, lowercase_   :Any							)->							str:
     if torch.is_tensor(lowercase_							):
         self.expand_frame(get_abs_min_max(lowercase_		, lowercase_							)							)
         if detect_overflow(lowercase_		, lowercase_							):
             A__       =    True
     elif var is None:
         self.expand_frame(F"{'None':>17} {ctx}"							)
     else:
         self.expand_frame(F"{'not a tensor':>17} {ctx}"							)
 def   UpperCAmelCase_							(       self   :Union[str, Any]							)->							str:
     self.expand_frame(F"\n\n{self.prefix} *** Starting batch number={self.batch_number} ***"							)
     self.expand_frame(F"{'abs min':8} {'abs max':8} metadata"							)
 def   UpperCAmelCase_							(       self   :int							)->							int:
     self.expand_frame(F"{self.prefix} *** Finished batch number={self.batch_number-1} ***\n\n"							)
 def   UpperCAmelCase_							(       self   :Optional[int]		, lowercase_   :Dict		, lowercase_   :Dict		, lowercase_   :str							)->							int:
     self.expand_frame(F"{self.prefix} {self.module_names[module]} {module.__class__.__name__}"							)

     # params
     for name, p in module.named_parameters(recurse=lowercase_							):
         self.analyse_variable(lowercase_		, lowercase_							)

     # inputs
     if isinstance(lowercase_		, lowercase_							):
         for i, x in enumerate(lowercase_							):
             self.analyse_variable(lowercase_		, F"input[{i}]"							)
     else:
         self.analyse_variable(lowercase_		, "input"							)

     # outputs
     if isinstance(lowercase_		, lowercase_							):
         for i, x in enumerate(lowercase_							):
             # possibly a tuple of tuples
             if isinstance(lowercase_		, lowercase_							):
                 for j, y in enumerate(lowercase_							):
                     self.analyse_variable(lowercase_		, F"output[{i}][{j}]"							)
             else:
                 self.analyse_variable(lowercase_		, F"output[{i}]"							)
     else:
         self.analyse_variable(lowercase_		, "output"							)

     self.save_frame()
 def   UpperCAmelCase_							(       self   :Any							)->							int:
     self.model.apply(self._register_forward_hook							)
 def   UpperCAmelCase_							(       self   :Tuple		, lowercase_   :Optional[int]							)->							Tuple:
     module.register_forward_hook(self.forward_hook							)



 def   UpperCAmelCase_							(       self   :List[str]		, lowercase_   :int		, lowercase_   :Optional[Any]		, lowercase_   :Dict							)->							Union[str, Any]:
     # - input is a tuple of packed inputs (could be non-Tensors)
     # - output could be a Tensor or a tuple of Tensors and non-Tensors

     A__       =    False

     A__       =    True if self.batch_number in self.trace_batch_nums else False
     if trace_mode:
         self.reset_saved_frames()

     if self.total_calls == 0:
         self.batch_start_frame()
     self.total_calls += 1

     # count batch numbers - the very first forward hook of the batch will be called when the
     # batch completes - i.e. it gets called very last - we know this batch has finished
     if module == self.model:
         self.batch_number += 1
         A__       =    True

     self.create_frame(lowercase_		, lowercase_		, lowercase_							)

     # if last_frame_of_batch:
     #     self.batch_end_frame()

     if trace_mode:
         self.trace_frames()

     if last_frame_of_batch:
         self.batch_start_frame()

     if self.detected_overflow and not trace_mode:
         self.dump_saved_frames()

         # now we can abort, as it's pointless to continue running
         raise ValueError(
             "DebugUnderflowOverflow: inf/nan detected, aborting as there is no point running further. "
             "Please scroll up above this traceback to see the activation values prior to this event."							)

     # abort after certain batch if requested to do so
     if self.abort_after_batch_num is not None and self.batch_number > self.abort_after_batch_num:
         raise ValueError(
             F"DebugUnderflowOverflow: aborting after {self.batch_number} batches due to"
             F" `abort_after_batch_num={self.abort_after_batch_num}` arg"							)





def 		UpperCamelCase       (							_lowerCamelCase      :      Dict		, _lowerCamelCase      :      int ):
    A__       =    var.abs()
    return F"{abs_var.min():8.2e} {abs_var.max():8.2e} {ctx}"





def 		UpperCamelCase       (							_lowerCamelCase      :      Tuple		, _lowerCamelCase      :      Optional[int] ):
    A__       =    False
    if torch.isnan(_lowerCamelCase ).any().item():
        A__       =    True
        print(F"{ctx} has nans" )
    if torch.isinf(_lowerCamelCase ).any().item():
        A__       =    True
        print(F"{ctx} has infs" )

    # if needed to monitor large elements can enable the following
    if 0:  # and detected:
        A__       =    var[torch.ge(var.abs()		, 1_00 )]
        if naaa.numel() > 0:
            print(F"{ctx}:  n100={naaa.numel()}" )
        A__       =    var[torch.ge(var.abs()		, 10_00 )]
        if naaaa.numel() > 0:
            print(F"{ctx}: n1000={naaaa.numel()}" )
        A__       =    var[torch.ge(var.abs()		, 1_00_00 )]
        if naaaaa.numel() > 0:
            print(F"{ctx}: n10000={naaaaa.numel()}" )

    if 0:
        print(F"min={var.min():9.2e} max={var.max():9.2e}" )

    if 0:
        print(F"min={var.min():9.2e} max={var.max():9.2e} var={var.var():9.2e} mean={var.mean():9.2e} ({ctx})" )

    return detected






class      UpperCAmelCase			( UpperCamelCase__       ):
 __lowercase     	=       """underflow_overflow"""
 __lowercase     	=       """tpu_metrics_debug"""



