As the holidays come to an end, I have completed (well not finished, but been working on while I had free time) Advent of Code. I’ve talked about this in years past, but the short of it is 25 days of coding problems. I like it because it generally challenges me to learn new things and think creatively with my Python (what I choose to use, but the are people who do this in Excel, AWK, and every language you can think of).
Day 7 has to do with playing a game of Camel Cards. To play, you’re given a list of hands that you have, along with the bid you played for each hand. The first part of the problem requires you to figure out how many points you go based on not only on the type of hand you have (full house vs two pair for example), but also how strong the hand was to the others of that same type.
To determine why type of hand I had, I built a function that uses the Counter
library within Python to automatically determine how many of each type of card are in each hand.
def categorize_hand(hand): from collections import Counter hand = list(Counter(hand).values()) hand.sort(reverse=True) if hand[0] == 5: return "5ofKind" elif hand[0] == 4: return "4ofKind" elif hand[0] == 3 and hand[1] == 2: return "fullhouse" elif hand[0] == 3: return "3ofKind" elif hand[0] == 2 and hand[1] == 2: return "2pair" elif hand[0] == 2: return "pair" else: return "high"
The function takes the list of cards in the hand, and returns a list of count of Card types. I don’t care how many of each card are present, only the total number of a card (any card), and then sort it from high to low. After that, if I look at the count of the first (and sometimes) second highest cards, I can classify it as 5 of a kind all the way to a simple high card.
The harder part of this problem for me was sorting the strength of the hands by type. When each hand was classified, I added it to a dictionary of lists that sorted by type. At the end though, I had to order the hands by the best to worst hand within that type. I thought about a lot of different ways to do this and hated all of them. My original idea for a sort function was going to be super complicated and not very efficient. And then I had an idea.
Most of the cards (2-9) were represented as an integer value already. Facecards and 10s on the other hand were represented by a letter. As luck would have it, there are 4 face cards (A, K, Q, J) and 10 (T). While those don’t translate over to hex values, it’s easy enough to replace them in order to a valid hex value. Aces (A) is a valid hex character, but relatively weak compared to the other letters so it became E. K became D, Q went to C, J to B, and T to A. From there, it was a simple translation of the hex string to an integer. The important part here isn’t the overall value of the number itself, simply its value relative to the others within the type of hand. From there it was a simple sort.
def hand_to_int(hand): hand = hand.replace("A", "E") hand = hand.replace("K", "D") hand = hand.replace("Q", "C") hand = hand.replace("J", "B") hand = hand.replace("T", "A") score = int(hand, 16) return score