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

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))