83 lines
2.4 KiB
Python
83 lines
2.4 KiB
Python
from collections import deque
|
|
|
|
|
|
def read_decks():
|
|
with open('day22/input') as reader:
|
|
first, second = reader.read().split('\n\n')
|
|
player1 = [int(i) for i in first.split('\n')[1:]]
|
|
player2 = [int(i) for i in second.split('\n')[1:] if i != '']
|
|
return deque(player1), deque(player2)
|
|
|
|
|
|
def play_part1(player1, player2):
|
|
while player1 and player2:
|
|
p1_top = player1.popleft()
|
|
p2_top = player2.popleft()
|
|
|
|
if p1_top > p2_top:
|
|
player1.append(p1_top)
|
|
player1.append(p2_top)
|
|
else:
|
|
player2.append(p2_top)
|
|
player2.append(p1_top)
|
|
|
|
return player1, player2
|
|
|
|
|
|
def calc_result(deck):
|
|
return sum([(i+1) * card for i, card in enumerate(reversed(deck))])
|
|
|
|
|
|
player1, player2 = read_decks()
|
|
|
|
# beware part one does not work in case of recursion, as there is no recursion rule yet
|
|
player1_part1, player2_part1 = play_part1(deque(player1), deque(player2))
|
|
|
|
|
|
winner_deck_part1 = player1_part1 if player1_part1 else player2_part1
|
|
|
|
res_part1 = calc_result(winner_deck_part1)
|
|
|
|
print(res_part1)
|
|
|
|
|
|
def play_part2(player1, player2):
|
|
states = set()
|
|
while player1 and player2:
|
|
p1_top = player1.popleft()
|
|
p2_top = player2.popleft()
|
|
|
|
new_state = (p1_top, p2_top, tuple(player1), tuple(player2))
|
|
if new_state in states:
|
|
return True, None, None # player 1 won, but do not return decks in case of errors. Should not happen in case of normal input, except recursive test case ;)
|
|
states.add(new_state)
|
|
|
|
if len(player1) >= p1_top and len(player2) >= p2_top:
|
|
player1_subgame = deque(list(player1)[:p1_top])
|
|
player2_subgame = deque(list(player2)[:p2_top])
|
|
player1_won, _, _ = play_part2(player1_subgame, player2_subgame)
|
|
if player1_won:
|
|
player1.append(p1_top)
|
|
player1.append(p2_top)
|
|
else:
|
|
player2.append(p2_top)
|
|
player2.append(p1_top)
|
|
else:
|
|
if p1_top > p2_top:
|
|
player1.append(p1_top)
|
|
player1.append(p2_top)
|
|
else:
|
|
player2.append(p2_top)
|
|
player2.append(p1_top)
|
|
|
|
return bool(player1), player1, player2
|
|
|
|
|
|
player1_won, player1_part2, player2_part2 = play_part2(player1, player2)
|
|
|
|
winner_deck_part2 = player1_part2 if player1_won else player2_part2
|
|
|
|
res_part2 = calc_result(winner_deck_part2)
|
|
|
|
print(res_part2)
|