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