22_spacecards.py 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. #!/usr/bin/env python3
  2. import sys
  3. from functools import partial, reduce
  4. # get modular multiplicative inverse for prime p
  5. def prime_modinv(p, mod):
  6. return pow(p, mod - 2, mod)
  7. # get (a, b) coefficients for inverse linear index mapping functions ax+b
  8. def inverse_functions(instructions, ncards):
  9. for line in reversed(instructions):
  10. if line == 'deal into new stack\n':
  11. yield -1, ncards - 1
  12. elif line.startswith('cut'):
  13. amount = int(line.split()[1])
  14. yield 1, amount
  15. else:
  16. increment = int(line.split()[-1])
  17. yield prime_modinv(increment, ncards), 0
  18. # compose all inverse mappings into a single linear function
  19. def inverse_function(instructions, ncards):
  20. functions = inverse_functions(instructions, ncards)
  21. return reduce(partial(fcompose, ncards), functions, (1, 0))
  22. # compose linear functions ax+b and cx+d
  23. def fcompose(mod, f, g):
  24. a, b = f
  25. c, d = g
  26. return c * a % mod, (c * b + d) % mod
  27. # compute f(x) = ax+b
  28. def fapply(f, x, mod):
  29. a, b = f
  30. return (a * x + b) % mod
  31. # repeat ax+b n times
  32. def frepeat(f, n, mod):
  33. if n == 0:
  34. return 1, 0
  35. if n == 1:
  36. return f
  37. half, odd = divmod(n, 2)
  38. g = frepeat(f, half, mod)
  39. gg = fcompose(mod, g, g)
  40. return fcompose(mod, f, gg) if odd else gg
  41. def find_card(value, ncards, instructions):
  42. f = inverse_function(instructions, ncards)
  43. return next(i for i in range(ncards) if fapply(f, i, ncards) == value)
  44. def card_at(index, ncards, nshuffles, instructions):
  45. f = inverse_function(instructions, ncards)
  46. fn = frepeat(f, nshuffles, ncards)
  47. return fapply(fn, index, ncards)
  48. instructions = list(sys.stdin)
  49. print(find_card(2019, 10007, instructions))
  50. print(card_at(2020, 119315717514047, 101741582076661, instructions))