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)