mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
91 lines
2.0 KiB
Python
91 lines
2.0 KiB
Python
from typing import List, TextIO
|
|
|
|
|
|
def shuffle(instructions: List[str], deck_size: int) -> List[int]:
|
|
deck = list(range(0, deck_size))
|
|
|
|
for instruction in instructions:
|
|
if "new stack" in instruction:
|
|
deck = list(reversed(deck))
|
|
continue
|
|
|
|
parts = instruction.split(" ")
|
|
if parts[0] == "cut":
|
|
by = int(parts[1])
|
|
|
|
new_deck = deck[by:]
|
|
new_deck += deck[:by]
|
|
|
|
deck = new_deck
|
|
else:
|
|
increment = int(parts[3])
|
|
|
|
new_deck = list(range(0, deck_size))
|
|
target_index = 0
|
|
|
|
for card in deck:
|
|
new_deck[target_index] = card
|
|
target_index = (target_index + increment) % len(deck)
|
|
|
|
deck = new_deck
|
|
|
|
return deck
|
|
|
|
|
|
def part1(data: TextIO) -> int:
|
|
instructions = [line.strip() for line in data]
|
|
|
|
result = shuffle(instructions, 10007)
|
|
|
|
for i, card in enumerate(result):
|
|
if card == 2019:
|
|
return i
|
|
|
|
raise Exception("Did not find card")
|
|
|
|
|
|
def modpow(a: int, b: int, m: int) -> int:
|
|
assert b >= 0
|
|
|
|
result = 1
|
|
n = a
|
|
|
|
while b > 0:
|
|
if b % 2:
|
|
result = (result * n) % m
|
|
|
|
b //= 2
|
|
n = (n * n) % m
|
|
|
|
return result
|
|
|
|
|
|
def inverse(a: int, m: int) -> int:
|
|
""" Computes the modulo multiplicative inverse """
|
|
return modpow(a, m - 2, m)
|
|
|
|
|
|
def part2(data: TextIO) -> int:
|
|
deck_size = 119315717514047
|
|
shuffles = 101741582076661
|
|
|
|
a, b = 1, 0
|
|
|
|
for line in data:
|
|
parts = line.split(' ')
|
|
if 'new stack' in line:
|
|
la, lb = -1, -1
|
|
elif parts[0] == 'deal':
|
|
la, lb = int(parts[-1]), 0
|
|
else:
|
|
la, lb = 1, -int(parts[-1])
|
|
|
|
a = (la * a) % deck_size
|
|
b = (la * b + lb) % deck_size
|
|
|
|
final_a = modpow(a, shuffles, deck_size)
|
|
final_b = ((b * (final_a - 1)) * inverse(a - 1, deck_size)) % deck_size
|
|
|
|
return ((2020 - final_b) * inverse(final_a, deck_size)) % deck_size
|
|
|