Update day22.py
This commit is contained in:
parent
bbcc9e1bb3
commit
df3cd1967a
|
@ -19,81 +19,42 @@ def parse_data() -> Tuple[list[int], list[int]]:
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def solve_p1(player1: list[int], player2: list[int]) -> int:
|
def play_game(player1: list[int], player2: list[int], rec: bool = False) -> Tuple[int, list[int]]:
|
||||||
stack1 = list(reversed(player1))
|
past_rounds: set[str] = set()
|
||||||
stack2 = list(reversed(player2))
|
hand1, hand2 = player1[:], player2[:]
|
||||||
|
|
||||||
while len(stack1) > 0 and len(stack2) > 0:
|
def snapshot() -> str:
|
||||||
number1 = stack1.pop()
|
return f"{hand1}{hand2}"
|
||||||
number2 = stack2.pop()
|
|
||||||
if number1 > number2:
|
while len(hand1) > 0 and len(hand2) > 0:
|
||||||
stack1.insert(0, number1)
|
if (curr_snapshot := snapshot()) in past_rounds:
|
||||||
stack1.insert(0, number2)
|
return 1, hand1
|
||||||
|
|
||||||
|
past_rounds.add(curr_snapshot)
|
||||||
|
card1, card2 = hand1.pop(0), hand2.pop(0)
|
||||||
|
|
||||||
|
if rec and len(hand1) >= card1 and len(hand2) >= card2:
|
||||||
|
winner, _ = play_game(hand1[:card1], hand2[:card2], rec=True)
|
||||||
else:
|
else:
|
||||||
stack2.insert(0, number2)
|
winner = 1 if card1 > card2 else 2
|
||||||
stack2.insert(0, number1)
|
|
||||||
|
|
||||||
winning = stack1 if len(stack1) > 0 else stack2
|
if winner == 1:
|
||||||
return sum(x*y for (x, y) in (zip(winning, [x for x in range(1, len(winning)+1)])))
|
hand1.append(card1)
|
||||||
|
hand1.append(card2)
|
||||||
|
else:
|
||||||
|
hand2.append(card2)
|
||||||
|
hand2.append(card1)
|
||||||
|
|
||||||
|
if len(hand2) == 0:
|
||||||
|
return 1, hand1
|
||||||
|
else:
|
||||||
|
return 2, hand2
|
||||||
|
|
||||||
|
|
||||||
|
def score(hand: list[int]) -> int:
|
||||||
|
return sum(x*y for (x, y) in zip(reversed(hand), [x for x in range(1, len(hand)+1)]))
|
||||||
|
|
||||||
|
|
||||||
PLAYER1, PLAYER2 = parse_data()
|
PLAYER1, PLAYER2 = parse_data()
|
||||||
print(solve_p1(PLAYER1, PLAYER2))
|
print(score(play_game(PLAYER1, PLAYER2, rec=False)[1]))
|
||||||
|
print(score(play_game(PLAYER1, PLAYER2, rec=True)[1]))
|
||||||
|
|
||||||
def play_game(cache: dict[str, int], player1: list[int], player2: list[int]) -> (int, list[int]):
|
|
||||||
previous_rounds: set[str] = set()
|
|
||||||
stack1, stack2 = list(reversed(player1)), list(reversed(player2))
|
|
||||||
|
|
||||||
def round_snapshot() -> str:
|
|
||||||
return f"{stack1}|{stack2}"
|
|
||||||
|
|
||||||
def normal_round() -> None:
|
|
||||||
_number1, _number2 = stack1.pop(), stack2.pop()
|
|
||||||
if _number1 > _number2:
|
|
||||||
stack1.insert(0, _number1)
|
|
||||||
stack1.insert(0, _number2)
|
|
||||||
else:
|
|
||||||
stack2.insert(0, _number2)
|
|
||||||
stack2.insert(0, _number1)
|
|
||||||
|
|
||||||
while len(stack1) > 0 and len(stack2) > 0:
|
|
||||||
if (snapshot := round_snapshot()) in previous_rounds:
|
|
||||||
return 1, stack1
|
|
||||||
else:
|
|
||||||
previous_rounds.add(snapshot)
|
|
||||||
|
|
||||||
if len(stack1) > stack1[len(stack1)-1] and len(stack2) > stack2[len(stack2)-1]:
|
|
||||||
number1, number2 = stack1.pop(), stack2.pop()
|
|
||||||
sub_deck1, sub_deck2 = stack1[1-number1:], stack2[1-number2:]
|
|
||||||
|
|
||||||
# Check cache for winner
|
|
||||||
if (sub_snapshot := f"{sub_deck1}|{sub_deck2}") not in cache:
|
|
||||||
winner, _ = play_game(cache, sub_deck1, sub_deck2)
|
|
||||||
cache[sub_snapshot] = winner
|
|
||||||
else:
|
|
||||||
winner = cache[sub_snapshot]
|
|
||||||
|
|
||||||
if winner == 1:
|
|
||||||
stack1.insert(0, number1)
|
|
||||||
stack1.insert(0, number2)
|
|
||||||
else:
|
|
||||||
stack2.insert(0, number2)
|
|
||||||
stack2.insert(0, number1)
|
|
||||||
else:
|
|
||||||
normal_round()
|
|
||||||
|
|
||||||
if len(stack1) > 0:
|
|
||||||
return 1, stack1
|
|
||||||
else:
|
|
||||||
return 2, stack2
|
|
||||||
|
|
||||||
|
|
||||||
# PART 2 is Broken for now
|
|
||||||
def solve_p2(player1: list[int], player2: list[int]) -> int:
|
|
||||||
cache: dict[str, int] = {}
|
|
||||||
winner, winning = play_game(cache, player1, player2)
|
|
||||||
return sum(x*y for (x, y) in (zip(winning, [x for x in range(1, len(winning)+1)])))
|
|
||||||
|
|
||||||
|
|
||||||
print(solve_p2(PLAYER1, PLAYER2))
|
|
||||||
|
|
Loading…
Reference in a new issue