import time from collections import Counter from pathlib import Path def timer(func): def wrapper(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) end_time = time.time() elapsed_time = end_time - start_time print(f"{func.__name__} time: {elapsed_time:.6f} seconds") return result return wrapper # 牌面数值映射 VAL = { "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9, "T": 10, "J": 11, "Q": 12, "K": 13, "A": 14, } def hand_key(cards: tuple[str, ...]) -> tuple[int, ...]: """ 将一手5张牌映射为规范元组。 元组的字典序即牌力大小,可直接用 > / < 比较。 """ # 1. 提取数值并降序排列 nums = sorted([VAL[c[0]] for c in cards], reverse=True) suits = {c[1] for c in cards} # 2. 判断同花与顺子 is_flush = len(suits) == 1 is_straight = len(set(nums)) == 5 and nums[0] - nums[4] == 4 # 3. 处理 A-2-3-4-5 顺子(A作为1,5-high) if nums == [14, 5, 4, 3, 2]: is_straight = True nums = [5, 4, 3, 2, 1] # 4. 统计出现次数,并按 (次数, 牌面) 降序排列 # 这是整个方法的数学核心:多重集的字典序 counts = Counter(nums) by_count = sorted(counts.items(), key=lambda x: (x[1], x[0]), reverse=True) # 5. 按牌型返回规范元组 if is_flush and is_straight: return (9, nums[0]) # 同花顺(皇家同花顺只是顶牌为A) if by_count[0][1] == 4: return (8, by_count[0][0], by_count[1][0]) # 四条 if by_count[0][1] == 3 and len(by_count) == 2: return (7, by_count[0][0], by_count[1][0]) # 葫芦 if is_flush: return (6, *nums) # 同花:比全部5张降序 if is_straight: return (5, nums[0]) # 顺子:比顶牌 if by_count[0][1] == 3: return (4, by_count[0][0], by_count[1][0], by_count[2][0]) # 三条 if by_count[0][1] == 2 and len(by_count) == 3: return (3, by_count[0][0], by_count[1][0], by_count[2][0]) # 两对 if by_count[0][1] == 2: return ( 2, by_count[0][0], by_count[1][0], by_count[2][0], by_count[3][0], ) # 一对 return (1, *nums) # 高牌:比全部5张降序 def read_hands(path: Path): with open(path) as f: for line in f: cards = line.strip().split() if len(cards) == 10: yield tuple(cards[:5]), tuple(cards[5:]) @timer def main() -> int: data_path = Path(__file__).parent / "0054_poker.txt" wins = sum(1 for p1, p2 in read_hands(data_path) if hand_key(p1) > hand_key(p2)) return wins if __name__ == "__main__": print(main())