Day 7
This commit is contained in:
parent
4ca74a8e4c
commit
d60382cc82
1000
d07/input.txt
Normal file
1000
d07/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
132
d07/main.py
Normal file
132
d07/main.py
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
from collections import Counter
|
||||||
|
from enum import auto
|
||||||
|
from enum import Enum
|
||||||
|
from enum import StrEnum
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
FACE_VALUES = {
|
||||||
|
"A": 14,
|
||||||
|
"K": 13,
|
||||||
|
"Q": 12,
|
||||||
|
"J": 11,
|
||||||
|
"T": 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def card_value(card: str) -> int:
|
||||||
|
if card.isnumeric():
|
||||||
|
return int(card)
|
||||||
|
|
||||||
|
return FACE_VALUES[card]
|
||||||
|
|
||||||
|
|
||||||
|
class HandType(Enum):
|
||||||
|
HIGH_CARD = auto()
|
||||||
|
ONE_PAIR = auto()
|
||||||
|
TWO_PAIR = auto()
|
||||||
|
THREE_OF_A_KIND = auto()
|
||||||
|
FULL_HOUSE = auto()
|
||||||
|
FOUR_OF_A_KIND = auto()
|
||||||
|
FIVE_OF_A_KIND = auto()
|
||||||
|
|
||||||
|
|
||||||
|
class Hand:
|
||||||
|
def __init__(self, cards: str, bid: int, use_jokers=False):
|
||||||
|
self.cards = cards
|
||||||
|
self.bid = bid
|
||||||
|
|
||||||
|
self.hand_type: HandType = HandType.HIGH_CARD
|
||||||
|
|
||||||
|
counts = Counter(self.cards)
|
||||||
|
jokers = counts["J"]
|
||||||
|
|
||||||
|
for card, count in counts.most_common():
|
||||||
|
if count == 5 or (use_jokers and card != "J" and count + jokers >= 5):
|
||||||
|
self.hand_type = HandType.FIVE_OF_A_KIND
|
||||||
|
if count != 5:
|
||||||
|
jokers -= 5 - count
|
||||||
|
break
|
||||||
|
# It's always better to use the jokers to improve a hand
|
||||||
|
if use_jokers and card == "J":
|
||||||
|
continue
|
||||||
|
if count == 4 or count + jokers >= 4:
|
||||||
|
self.hand_type = HandType.FOUR_OF_A_KIND
|
||||||
|
if count != 4:
|
||||||
|
jokers -= 4 - count
|
||||||
|
break
|
||||||
|
if count == 3 or count + jokers >= 3:
|
||||||
|
if self.hand_type == HandType.HIGH_CARD:
|
||||||
|
self.hand_type = HandType.THREE_OF_A_KIND
|
||||||
|
elif self.hand_type == HandType.ONE_PAIR:
|
||||||
|
self.hand_type = HandType.FULL_HOUSE
|
||||||
|
if count != 3:
|
||||||
|
jokers -= 3 - count
|
||||||
|
continue
|
||||||
|
if count == 2 or count + jokers >= 2:
|
||||||
|
if self.hand_type == HandType.HIGH_CARD:
|
||||||
|
self.hand_type = HandType.ONE_PAIR
|
||||||
|
elif self.hand_type == HandType.ONE_PAIR:
|
||||||
|
self.hand_type = HandType.TWO_PAIR
|
||||||
|
elif self.hand_type == HandType.THREE_OF_A_KIND:
|
||||||
|
self.hand_type = HandType.FULL_HOUSE
|
||||||
|
if count != 2:
|
||||||
|
jokers -= 2 - count
|
||||||
|
continue
|
||||||
|
|
||||||
|
def __lt__(self, other: "Hand") -> bool:
|
||||||
|
# print(f"Comparing {self} to {other}")
|
||||||
|
if self.hand_type == other.hand_type:
|
||||||
|
for s, o in zip(self.cards, other.cards):
|
||||||
|
if s != o:
|
||||||
|
return card_value(s) < card_value(o)
|
||||||
|
|
||||||
|
return self.hand_type.value < other.hand_type.value
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return f"<{self.cards} {self.bid}: {self.hand_type}>"
|
||||||
|
|
||||||
|
|
||||||
|
def part1(input: Path) -> int:
|
||||||
|
hands: list[Hand] = []
|
||||||
|
with input.open() as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
parts = line.partition(" ")
|
||||||
|
hands.append(Hand(parts[0], int(parts[2])))
|
||||||
|
|
||||||
|
answer = 0
|
||||||
|
for i, hand in enumerate(sorted(hands)):
|
||||||
|
print(hand)
|
||||||
|
answer += (i + 1) * hand.bid
|
||||||
|
|
||||||
|
return answer
|
||||||
|
|
||||||
|
|
||||||
|
def part2(input: Path) -> int:
|
||||||
|
FACE_VALUES["J"] = 1
|
||||||
|
|
||||||
|
hands: list[Hand] = []
|
||||||
|
with input.open() as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
parts = line.partition(" ")
|
||||||
|
hands.append(Hand(parts[0], int(parts[2]), use_jokers=True))
|
||||||
|
|
||||||
|
answer = 0
|
||||||
|
for i, hand in enumerate(sorted(hands)):
|
||||||
|
print(hand)
|
||||||
|
answer += (i + 1) * hand.bid
|
||||||
|
|
||||||
|
return answer
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
input = Path("input.txt")
|
||||||
|
# input = Path("sub-test.txt")
|
||||||
|
# input = Path("sample.txt")
|
||||||
|
result1 = part1(input)
|
||||||
|
print("part1", result1)
|
||||||
|
|
||||||
|
result2 = part2(input)
|
||||||
|
print("part2", result2)
|
5
d07/sample.txt
Normal file
5
d07/sample.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
32T3K 765
|
||||||
|
T55J5 684
|
||||||
|
KK677 28
|
||||||
|
KTJJT 220
|
||||||
|
QQQJA 483
|
1
d07/sub-test.txt
Normal file
1
d07/sub-test.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
Q76JJ 123
|
Loading…
Reference in New Issue
Block a user