Skip to content

Commit d34f6b7

Browse files
committed
y2023 d7 p1
1 parent ca45d36 commit d34f6b7

File tree

3 files changed

+1121
-0
lines changed

3 files changed

+1121
-0
lines changed

src/advent_of_code/y2023/d7.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
from dataclasses import dataclass
2+
from functools import cached_property, total_ordering
3+
4+
from advent_of_code.util import format_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+
class CamelCardsHand:
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+
def hand_type_strength(self) -> int:
28+
card_value_counts = {
29+
v: sum(1 for c in self.cards if c == v) for v in set(self.cards)
30+
}
31+
card_counts = card_value_counts.values()
32+
33+
if set(card_counts) == {5}:
34+
return FIVE_OF_A_KIND
35+
elif set(card_counts) == {4, 1}:
36+
return FOUR_OF_A_KIND
37+
elif set(card_counts) == {3, 2}:
38+
return FULL_HOUSE
39+
elif set(card_counts) == {3, 1}:
40+
return THREE_OF_A_KIND
41+
elif sorted(card_counts) == [1, 2, 2]:
42+
return TWO_PAIR
43+
elif 2 in card_counts:
44+
return ONE_PAIR
45+
else:
46+
return HIGH_CARD
47+
48+
def __eq__(self, other: "CamelCardsHand") -> bool:
49+
return self.cards == other.cards
50+
51+
def __lt__(self, other: "CamelCardsHand") -> bool:
52+
if self.hand_type_strength < other.hand_type_strength:
53+
return True
54+
if self.hand_type_strength == other.hand_type_strength:
55+
for self_num, other_num in zip(self.cards, other.cards):
56+
if self_num < other_num:
57+
return True
58+
elif self_num == other_num:
59+
continue
60+
else:
61+
return False
62+
return False
63+
64+
@classmethod
65+
def from_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] if v in values_map else int(v) for v in cards_part
78+
)
79+
80+
return cls(
81+
bid=int(bid_part),
82+
cards=card_values,
83+
)
84+
85+
86+
def part_1(cards_input: list[str]) -> int:
87+
hands = [CamelCardsHand.from_input(line) for line in cards_input]
88+
89+
return sum(i * hand.bid for i, hand in enumerate(sorted(hands), start=1))
90+
91+
92+
def part_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+
)

0 commit comments

Comments
 (0)