Browse Source

Day 7

master
Noëlle Anthony 4 months ago
parent
commit
39b1b108c1
3 changed files with 1218 additions and 0 deletions
  1. 86
    0
      day07-1.py
  2. 132
    0
      day07-2.py
  3. 1000
    0
      day07.input

+ 86
- 0
day07-1.py View File

@@ -0,0 +1,86 @@
from collections import Counter

from helpers import Helper

helper = Helper(debug=True)
debug = helper.debug
load_input = helper.load_input

CARD_VALUES = []
for i in range(2,10):
CARD_VALUES.append(str(i))
CARD_VALUES.extend(["T", "J", "Q", "K", "A"])

HAND_VALUES = [
"High card",
"One pair",
"Two pair",
"Three of a kind",
"Full House",
"Four of a kind",
"Five of a kind"
]

class Hand:
def __init__(self, cards, bid):
self.cards = cards
self.bid = bid

@property
def value(self):
card_counter = Counter(self.cards)
card_counts = card_counter .most_common()
if card_counts[0][1] == 5:
return "Five of a kind"
if card_counts[0][1] == 4:
return "Four of a kind"
if card_counts[0][1] == 3:
if card_counts[1][1] == 2:
return "Full House"
return "Three of a kind"
if card_counts[0][1] == 2:
if card_counts[1][1] == 2:
return "Two pair"
return "One pair"
return "High card"

def __lt__(self, other):
# They have different hand values
if self.value != other.value:
return HAND_VALUES.index(self.value) < HAND_VALUES.index(other.value)
# They have the same hand value
# So check each card in sequence
for i in range(len(self.cards)):
if self.cards[i] != other.cards[i]:
# They have different nth cards
return CARD_VALUES.index(self.cards[i]) < CARD_VALUES.index(other.cards[i])
# They're the same
return False
def __str__(self):
return f"Camel Cards hand: {self.cards} (value {self.value}, bid {self.bid})"
def __repr__(self):
return self.__str__()

def main():
lines = load_input(7)
hands = []
for line in lines:
cards, bid = line.split()
hands.append(Hand(
cards = cards,
bid = bid
))
hands.sort()
print(hands[:10])

total_winnings = 0
for i, hand in enumerate(hands):
total_winnings += ((i+1) * int(hand.bid))

print(f"Total winnings: {total_winnings}")

if __name__ == "__main__":
main()

+ 132
- 0
day07-2.py View File

@@ -0,0 +1,132 @@
from collections import Counter

from helpers import Helper

helper = Helper(debug=True)
debug = helper.debug
load_input = helper.load_input

CARD_VALUES = ["J"]
for i in range(2,10):
CARD_VALUES.append(str(i))
CARD_VALUES.extend(["T", "Q", "K", "A"])

HAND_VALUES = [
"High card",
"One pair",
"Two pair",
"Three of a kind",
"Full House",
"Four of a kind",
"Five of a kind"
]

class Hand:
def __init__(self, cards, bid):
self.cards = cards
self.bid = bid

@property
def value(self):
card_counter = Counter(self.cards)
card_counts = card_counter.most_common()
# We have to separate J being the most common card out,
# or else it might get counted twice.
if card_counts[0][0] == "J":
# Five jacks is five of a kind.
# Four jacks is five of a kind too, because the other card counts.
# Three jacks plus two of another card is five of a kind.
if (card_counts[0][1] == 5
or card_counts[0][1] == 4
or (card_counts[0][1] == 3 and card_counts[1][1] == 2)
):
return "Five of a kind"
# Three jacks is four of a kind, because the next most common card counts.
# Two jacks plus two of another card is four of a kind.
if (card_counts[0][1] == 3
or (card_counts[0][1] == 2 and card_counts[1][1] == 2)
):
return "Four of a kind"
# Weirdly, you can only get a full house if there's only one jack...
# and if that's the case, it won't be at the front of most_common().
if card_counts[0][1] == 2:
return "Three of a kind"
# If J is at the front of most_common(), and there's only one of it,
# then there's no more than 1 of any other card. So we have a pair.
return "One pair"
# Okay, done with J being at the front.
# There are five cards of a kind, or (three/four) cards of a kind and
# (one/two) J.
# If there are only two of a kind at the front, then there aren't more
# than two of any other kind, so we can't get to 5.
if card_counts[0][1] == 5 or card_counts[0][1] + card_counter["J"] == 5:
return "Five of a kind"
# There are four cards of a kind without a J, or (two/three) cards of
# a kind and (one/two) J.
if card_counts[0][1] == 4 or card_counts[0][1] + card_counter["J"] == 4:
return "Four of a kind"
# There are three cards of a kind without a J, or two cards of a kind and
# exactly one J.
if card_counts[0][1] == 3 or card_counts[0][1] + card_counter["J"] == 3:
# We know the most common card isn't a J; we already covered that
# in a separate branch.
# If the most common count is 3 and there's a J, we already covered
# that too, with four and five of a kind.
# If the most common count is 2 and there are 2 Js, we already covered
# that with four of a kind.
# So if the most common count is 2 and there's a J, it can't be in second
# position, and if the most common count is 3 then there can't be a J.
# So we can discard the possibility that J is in second position.
if card_counts[1][1] == 2:
return "Full House"
return "Three of a kind"
# There are two of the most common card without any Js, or one and a single J.
if card_counts[0][1] == 2 or card_counts[0][1] + card_counter["J"] == 2:
# Same logic as above. If J were the second-most-common card we'd have
# already encountered it.
if card_counts[1][1] == 2:
return "Two pair"
return "One pair"
return "High card"

def __lt__(self, other):
# They have different hand values
if self.value != other.value:
return HAND_VALUES.index(self.value) < HAND_VALUES.index(other.value)
# They have the same hand value
# So check each card in sequence
for i in range(len(self.cards)):
if self.cards[i] != other.cards[i]:
# They have different nth cards
return CARD_VALUES.index(self.cards[i]) < CARD_VALUES.index(other.cards[i])
# They're the same
return False
def __str__(self):
return f"Camel Cards hand: {self.cards} (value {self.value}, bid {self.bid})"
def __repr__(self):
return self.__str__()

def main():
lines = load_input(7)
hands = []
for line in lines:
cards, bid = line.split()
hands.append(Hand(
cards = cards,
bid = bid
))
hands.sort()
print(hands[:10])

total_winnings = 0
for i, hand in enumerate(hands):
total_winnings += ((i+1) * int(hand.bid))

print(f"Total winnings: {total_winnings}")

if __name__ == "__main__":
main()

+ 1000
- 0
day07.input
File diff suppressed because it is too large
View File


Loading…
Cancel
Save