|
| 1 | +fromdataclassesimportdataclass |
| 2 | +fromfunctoolsimportcached_property,total_ordering |
| 3 | + |
| 4 | +fromadvent_of_code.utilimportformat_solution,puzzle_input |
| 5 | + |
| 6 | +HIGH_CARD=1 |
| 7 | +ONE_PAIR=2 |
| 8 | +TWO_PAIR=3 |
| 9 | +THREE_OF_A_KIND=4 |
| 10 | +FULL_HOUSE=5 |
| 11 | +FOUR_OF_A_KIND=6 |
| 12 | +FIVE_OF_A_KIND=7 |
| 13 | + |
| 14 | + |
| 15 | +@total_ordering |
| 16 | +@dataclass(frozen=True) |
| 17 | +classCamelCardsHand: |
| 18 | +""" |
| 19 | + Represent a hand with a bid in a game of Camel Cards |
| 20 | + """ |
| 21 | + |
| 22 | +bid:int |
| 23 | + |
| 24 | +cards:tuple[int,int,int,int,int] |
| 25 | + |
| 26 | +@cached_property |
| 27 | +defhand_type_strength(self)->int: |
| 28 | +card_value_counts= { |
| 29 | +v:sum(1forcinself.cardsifc==v)forvinset(self.cards) |
| 30 | + } |
| 31 | +card_counts=card_value_counts.values() |
| 32 | + |
| 33 | +ifset(card_counts)== {5}: |
| 34 | +returnFIVE_OF_A_KIND |
| 35 | +elifset(card_counts)== {4,1}: |
| 36 | +returnFOUR_OF_A_KIND |
| 37 | +elifset(card_counts)== {3,2}: |
| 38 | +returnFULL_HOUSE |
| 39 | +elifset(card_counts)== {3,1}: |
| 40 | +returnTHREE_OF_A_KIND |
| 41 | +elifsorted(card_counts)== [1,2,2]: |
| 42 | +returnTWO_PAIR |
| 43 | +elif2incard_counts: |
| 44 | +returnONE_PAIR |
| 45 | +else: |
| 46 | +returnHIGH_CARD |
| 47 | + |
| 48 | +def__eq__(self,other:"CamelCardsHand")->bool: |
| 49 | +returnself.cards==other.cards |
| 50 | + |
| 51 | +def__lt__(self,other:"CamelCardsHand")->bool: |
| 52 | +ifself.hand_type_strength<other.hand_type_strength: |
| 53 | +returnTrue |
| 54 | +ifself.hand_type_strength==other.hand_type_strength: |
| 55 | +forself_num,other_numinzip(self.cards,other.cards): |
| 56 | +ifself_num<other_num: |
| 57 | +returnTrue |
| 58 | +elifself_num==other_num: |
| 59 | +continue |
| 60 | +else: |
| 61 | +returnFalse |
| 62 | +returnFalse |
| 63 | + |
| 64 | +@classmethod |
| 65 | +deffrom_input(cls,input_line:str)->"CamelCardsHand": |
| 66 | +cards_part,bid_part=input_line.split() |
| 67 | + |
| 68 | +values_map= { |
| 69 | +"T":10, |
| 70 | +"J":11, |
| 71 | +"Q":12, |
| 72 | +"K":13, |
| 73 | +"A":14, |
| 74 | + } |
| 75 | + |
| 76 | +card_values=tuple( |
| 77 | +values_map[v]ifvinvalues_mapelseint(v)forvincards_part |
| 78 | + ) |
| 79 | + |
| 80 | +returncls( |
| 81 | +bid=int(bid_part), |
| 82 | +cards=card_values, |
| 83 | + ) |
| 84 | + |
| 85 | + |
| 86 | +defpart_1(cards_input:list[str])->int: |
| 87 | +hands= [CamelCardsHand.from_input(line)forlineincards_input] |
| 88 | + |
| 89 | +returnsum(i*hand.bidfori,handinenumerate(sorted(hands),start=1)) |
| 90 | + |
| 91 | + |
| 92 | +defpart_2(cards_input:list[str])->int: |
| 93 | +pass |
| 94 | + |
| 95 | + |
| 96 | +if__name__=="__main__": |
| 97 | +puzzle=puzzle_input(2023,7) |
| 98 | + |
| 99 | +print( |
| 100 | +format_solution( |
| 101 | +solver_p1=lambda:part_1(puzzle), |
| 102 | +solver_p2=lambda:part_2(puzzle), |
| 103 | + ) |
| 104 | + ) |