You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
4.6 KiB
190 lines
4.6 KiB
lines = open('inputs/day7.txt').readlines()
|
|
strength = ['A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4', '3', '2'][::-1]
|
|
strength2 = ['J'] + strength[:9] + strength[10:]
|
|
|
|
|
|
def parse_hands(lines: list[str]) -> tuple:
|
|
hands, bids = [], []
|
|
for line in lines:
|
|
hands.append(line.split()[0])
|
|
bids.append(line.split()[1])
|
|
return hands, [int(x) for x in bids]
|
|
|
|
def rel_occ(hand: str) -> list[int]:
|
|
occ = []
|
|
for i in hand:
|
|
occ.append(hand.count(i))
|
|
return occ
|
|
|
|
def fiveofakind(hand: str, j: int) -> bool:
|
|
if j == 5:
|
|
return True
|
|
elif j == 4:
|
|
return True
|
|
elif j == 3:
|
|
return onepair(hand, 0) or twopair(hand, 0)
|
|
elif j == 2:
|
|
return threeofakind(hand, 0)
|
|
elif j == 1:
|
|
return fourofakind(hand, 0)
|
|
else:
|
|
if rel_occ(hand)[0] == 5:
|
|
return True
|
|
return False
|
|
|
|
def fourofakind(hand: str, j: int) -> bool:
|
|
if j == 3:
|
|
return True
|
|
elif j == 2:
|
|
return twopair(hand, 0)
|
|
elif j == 1:
|
|
return threeofakind(hand, 0)
|
|
else:
|
|
occ = rel_occ(hand)
|
|
for i in occ:
|
|
if i == 4:
|
|
return True
|
|
return False
|
|
|
|
def fullhouse(hand: str, j: int) -> bool:
|
|
if j == 3:
|
|
return True
|
|
elif j == 2:
|
|
occ = rel_occ(hand)
|
|
counter = 0
|
|
for i in occ:
|
|
if i == 2:
|
|
counter += 1
|
|
if counter == 4:
|
|
return True
|
|
elif j == 1:
|
|
return twopair(hand, 0)
|
|
else:
|
|
threes = False
|
|
twos = False
|
|
occ = rel_occ(hand)
|
|
for i in occ:
|
|
if i == 3:
|
|
threes = True
|
|
if i == 2:
|
|
twos = True
|
|
return twos and threes
|
|
|
|
def threeofakind(hand: str, j: int) -> bool:
|
|
if j == 2:
|
|
return True
|
|
if j == 1:
|
|
return onepair(hand, 0)
|
|
else:
|
|
threes = False
|
|
ones = False
|
|
occ = rel_occ(hand)
|
|
for i in occ:
|
|
if i == 3:
|
|
threes = True
|
|
if i == 1:
|
|
ones = True
|
|
return ones and threes
|
|
|
|
def twopair(hand: str, j: int) -> bool:
|
|
if j == 2:
|
|
return True
|
|
else:
|
|
occ = rel_occ(hand)
|
|
counter = 0
|
|
for i in occ:
|
|
if i == 2:
|
|
counter += 1
|
|
if counter == 4:
|
|
return True
|
|
return False
|
|
|
|
def onepair(hand: str, j:int) -> bool:
|
|
if j == 1:
|
|
return True
|
|
else:
|
|
occ = rel_occ(hand)
|
|
counter = 0
|
|
for i in occ:
|
|
if i == 2:
|
|
counter += 1
|
|
if counter == 2:
|
|
return True
|
|
return False
|
|
|
|
def value(hand: str, joker: bool) -> int:
|
|
if joker:
|
|
j = hand.count('J')
|
|
else:
|
|
j = 0
|
|
if fiveofakind(hand, j):
|
|
return 6
|
|
elif fourofakind(hand, j):
|
|
return 5
|
|
elif fullhouse(hand, j):
|
|
return 4
|
|
elif threeofakind(hand, j):
|
|
return 3
|
|
elif twopair(hand, j):
|
|
return 2
|
|
elif onepair(hand, j):
|
|
return 1
|
|
else:
|
|
return 0
|
|
|
|
def compare_equal(hand1: str, hand2: str, part2: bool = False) -> bool:
|
|
if part2:
|
|
for i in range(len(hand1)):
|
|
if strength2.index(hand1[i]) > strength2.index(hand2[i]):
|
|
return True
|
|
if strength2.index(hand1[i]) < strength2.index(hand2[i]):
|
|
return False
|
|
else:
|
|
for i in range(len(hand1)):
|
|
if strength.index(hand1[i]) > strength.index(hand2[i]):
|
|
return True
|
|
if strength.index(hand1[i]) < strength.index(hand2[i]):
|
|
return False
|
|
|
|
def stronger(hand1: str, hand2: str, part2: bool = False) -> bool:
|
|
if value(hand1, part2) > value(hand2, part2):
|
|
return True
|
|
elif value(hand1, part2) < value(hand2, part2):
|
|
return False
|
|
else:
|
|
return compare_equal(hand1, hand2, part2)
|
|
|
|
hands, bids = parse_hands(lines)
|
|
|
|
ranks1 = []
|
|
ranks2 = []
|
|
for j in range(len(hands)):
|
|
count1 = 0
|
|
count2 = 0
|
|
for i in range(len(hands)):
|
|
if hands[j] == hands[i]:
|
|
count1 += 1
|
|
count2 += 1
|
|
else:
|
|
if stronger(hands[j], hands[i]):
|
|
count1 += 1
|
|
if stronger(hands[j], hands[i], part2 = True):
|
|
count2 += 1
|
|
ranks1.append(count1)
|
|
ranks2.append(count2)
|
|
|
|
earnings1 = []
|
|
earnings2 = []
|
|
for bid, rank in zip(bids, ranks1):
|
|
earnings1.append(bid * rank)
|
|
for bid2, rank2 in zip(bids, ranks2):
|
|
earnings2.append(bid2 * rank2)
|
|
|
|
|
|
#print(f"Solution Part 1: {sum(earnings1)}")
|
|
|
|
#print(f"Solution Part 2: {sum(earnings2)}")
|
|
|
|
for hand in hands:
|
|
if hand.count('J') == 2:
|
|
print(hand, value(hand, True)) |