Day 7 - Advent of Code 2023
Working solutions for the day 7 puzzles.
Part One
""" day_07_01.py """
# usage: python3 day_07_01.py < input
import functools
import sys
def arrange(hand, sort=True):
""" format """
ref = {'A': 14, 'K': 13, 'Q': 12, 'J': 11, 'T': 10, '9': 9,
'8': 8, '7': 7, '6': 6, '5': 5, '4': 4, '3': 3, '2': 2}
x = [ref[i] for i in hand]
if sort:
return sorted(x)
return x
def x_of_a_kind(x, hand):
""" x of a kind """
for i in range(6 - x):
if len(set(hand[i:i + x])) == 1:
return True
return False
def five_of_a_kind(hand):
""" five of a kind """
return x_of_a_kind(5, hand)
def full_house(hand):
""" full house """
if not three_of_a_kind(hand):
return False
return len(set(hand)) == 2
def four_of_a_kind(hand):
""" four of a kind """
return x_of_a_kind(4, hand)
def three_of_a_kind(hand):
""" three of a kind """
return x_of_a_kind(3, hand)
def two_pair(hand):
""" two pair """
if not two_of_a_kind(hand):
return False
return len(set(hand)) == 3
def two_of_a_kind(hand):
""" two of a kind """
return x_of_a_kind(2, hand)
def high(hand1, hand2):
""" hand1 has high card per puzzle description """
h1, h2 = arrange(hand1[0], sort=False), arrange(hand2[0], sort=False)
for x, y in zip(h1, h2):
if x > y:
return 1
if y > x:
return -1
return 0
def wins(hand1, hand2):
""" hand 1 wins over hand 2 """
def helper(func):
""" win, lose or draw func """
x, y, z = func(h1), func(h2), high(hand1, hand2)
ref = {(True, True): z, (True, False): 1,
(False, True): -1, (False, False): 0}
return ref[(x, y)]
h1, h2 = arrange(hand1[0]), arrange(hand2[0])
for f in [five_of_a_kind, four_of_a_kind, full_house,
three_of_a_kind, two_pair, two_of_a_kind]:
if (outcome := helper(f)) != 0:
return outcome
return high(hand1, hand2)
hands = [line.split() for line in sys.stdin]
hands.sort(key=functools.cmp_to_key(wins))
print(sum((i + 1) * int(bid) for i, (_, bid) in enumerate(hands)))
Part Two
""" day_07_02.py """
# usage: python3 day_07_02.py < input
import functools
import sys
def arrange(hand, sort=True):
""" format """
ref = {'A': 14, 'K': 13, 'Q': 12, 'J': 1, 'T': 10, '9': 9,
'8': 8, '7': 7, '6': 6, '5': 5, '4': 4, '3': 3, '2': 2}
x = [ref[i] for i in hand]
if sort:
return sorted(x)
return x
def x_of_a_kind(x, hand):
""" x of a kind """
h = [i for i in hand if i != 1]
for i in range(6 - x):
if len(set(h[i:i + (x - (5 - len(h)))])) == 1:
return True
return hand == [1, 1, 1, 1, 1]
def five_of_a_kind(hand):
""" five of a kind """
return x_of_a_kind(5, hand)
def four_of_a_kind(hand):
""" four of a kind """
return x_of_a_kind(4, hand)
def full_house(hand):
""" full house """
if not three_of_a_kind(hand):
return False
return len(set(i for i in hand if i != 1)) == 2
def three_of_a_kind(hand):
""" three of a kind """
return x_of_a_kind(3, hand)
def two_pair(hand):
""" two pair """
if not two_of_a_kind(hand):
return False
return len(set(hand)) == 3
def two_of_a_kind(hand):
""" two of a kind """
return x_of_a_kind(2, hand)
def high(hand1, hand2):
""" hand1 has high card per puzzle description """
h1, h2 = arrange(hand1[0], sort=False), arrange(hand2[0], sort=False)
for x, y in zip(h1, h2):
if x > y:
return 1
if y > x:
return -1
return 0
def wins(hand1, hand2):
""" hand 1 wins over hand 2 """
def helper(func):
""" win, lose or draw func """
x, y, z = func(h1), func(h2), high(hand1, hand2)
ref = {(True, True): z, (True, False): 1,
(False, True): -1, (False, False): 0}
return ref[(x, y)]
h1, h2 = arrange(hand1[0]), arrange(hand2[0])
for f in [five_of_a_kind, four_of_a_kind, full_house,
three_of_a_kind, two_pair, two_of_a_kind]:
if (outcome := helper(f)) != 0:
return outcome
return high(hand1, hand2)
hands = [line.split() for line in sys.stdin]
hands.sort(key=functools.cmp_to_key(wins))
print(sum((i + 1) * int(bid) for i, (_, bid) in enumerate(hands)))