From e06c191e99c4c98c78a8bf651098bc46ad6b417d Mon Sep 17 00:00:00 2001 From: wieerwill Date: Thu, 7 Dec 2023 17:55:56 +0100 Subject: [PATCH] solve Day07 in python --- Day07/README.md | 24 +++++++++++++ Day07/python/solution2.py | 76 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 Day07/python/solution2.py diff --git a/Day07/README.md b/Day07/README.md index 770e7f4..96e96b6 100644 --- a/Day07/README.md +++ b/Day07/README.md @@ -51,3 +51,27 @@ So, the first step is to put the hands in order of strength: Now, you can determine the total winnings of this set of hands by adding up the result of multiplying each hand's bid with its rank (765 * 1 + 220 * 2 + 28 * 3 + 684 * 4 + 483 * 5). So the total winnings in this example are 6440. Find the rank of every hand in your set. What are the total winnings? + +## Part Two +To make things a little more interesting, the Elf introduces one additional rule. Now, J cards are jokers - wildcards that can act like whatever card would make the hand the strongest type possible. + +To balance this, J cards are now the weakest individual cards, weaker even than 2. The other cards stay in the same order: A, K, Q, T, 9, 8, 7, 6, 5, 4, 3, 2, J. + +J cards can pretend to be whatever card is best for the purpose of determining hand type; for example, QJJQ2 is now considered four of a kind. However, for the purpose of breaking ties between two hands of the same type, J is always treated as J, not the card it's pretending to be: JKKK2 is weaker than QQQQ2 because J is weaker than Q. + +Now, the above example goes very differently: +``` +32T3K 765 +T55J5 684 +KK677 28 +KTJJT 220 +QQQJA 483 +``` + +- 32T3K is still the only one pair; it doesn't contain any jokers, so its strength doesn't increase. +- KK677 is now the only two pair, making it the second-weakest hand. +- T55J5, KTJJT, and QQQJA are now all four of a kind! T55J5 gets rank 3, QQQJA gets rank 4, and KTJJT gets rank 5. + +With the new joker rule, the total winnings in this example are 5905. + +Using the new joker rule, find the rank of every hand in your set. What are the new total winnings? \ No newline at end of file diff --git a/Day07/python/solution2.py b/Day07/python/solution2.py new file mode 100644 index 0000000..d869261 --- /dev/null +++ b/Day07/python/solution2.py @@ -0,0 +1,76 @@ +import os +from collections import Counter + +def read_hands(file_path): + try: + with open(file_path, 'r') as file: + print("Reading hands...") + return [line.strip().split() for line in file] + except Exception as e: + print(f"Error reading file {file_path}: {e}") + raise + +def replace_face_cards(hand): + replacements = {'T': 'a', 'J': '1', 'Q': 'c', 'K': 'd', 'A': 'e'} + return ''.join(replacements.get(card, card) for card in hand) + +def strength(hand): + hand = replace_face_cards(hand) + C = Counter(hand) + target = max(C, key=lambda k: (C[k], k != '1')) # Find the target card, excluding joker + + if '1' in C and target != '1': + C[target] += C['1'] + del C['1'] + + if sorted(C.values()) == [5]: + category = 10 + elif sorted(C.values()) == [1,4]: + category = 9 + elif sorted(C.values()) == [2,3]: + category = 8 + elif sorted(C.values()) == [1,1,3]: + category = 7 + elif sorted(C.values()) == [1,2,2]: + category = 6 + elif sorted(C.values()) == [1,1,1,2]: + category = 5 + elif sorted(C.values()) == [1,1,1,1,1]: + category = 4 + else: + raise ValueError(f"Invalid hand: {C} {hand}") + + print(f"Hand: {hand}, Category: {category}") + return (category, hand) + +def hand_key(hand): + return strength(hand[0]) + +def calculate_total_winnings(file_path): + hands = read_hands(file_path) + print("Sorting hands based on strength...") + sorted_hands = sorted(hands, key=hand_key, reverse=True) + total_winnings = sum(int(bid) * (len(hands) - index) for index, (_, bid) in enumerate(sorted_hands)) + print("Calculating total winnings...") + return total_winnings + +def test(file_path): + print(f"Running test with {file_path}...") + try: + expected_result = 5905 + total_winnings = calculate_total_winnings(file_path) + assert total_winnings == expected_result, f"Test failed, expected {expected_result} but got {total_winnings}" + print(f"Test passed: {total_winnings}") + except Exception as e: + print(f"Test failed: {e}") + +def main(): + try: + test("../test.txt") + result = calculate_total_winnings("../input.txt") + print(f"Total result from input.txt: {result}") + except Exception as e: + print(f"An error occurred: {e}") + +if __name__ == "__main__": + main()