Solutions to Advent of Code 2017 https://adventofcode.com/2017/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

16.py 1.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. import string
  2. from functools import partial, reduce
  3. def spin(amount, line):
  4. return line[-amount:] + line[:-amount]
  5. def exchange(p1, p2, line):
  6. line[p1], line[p2] = line[p2], line[p1]
  7. return line
  8. def partner(n1, n2, line):
  9. p1, p2 = line.index(n1), line.index(n2)
  10. line[p1], line[p2] = line[p2], line[p1]
  11. return line
  12. def dance(reps, moves):
  13. line = list(string.ascii_lowercase[:16])
  14. # Maintain a history to try and find cycles. If we ever generate the same line twice
  15. # then all of the remainder will just cycle between those two lines.
  16. history = []
  17. for i in range(reps):
  18. line = reduce(lambda v, m: m(v), moves, line)
  19. if line in history:
  20. start = history.index(line)
  21. cycle = len(history) - start
  22. return ''.join(history[start + (reps - i - 1) % cycle])
  23. history.append(line[:]) # NB: Copy of the line, so it doesn't get mutated next cycle...
  24. return ''.join(line)
  25. instructions = {
  26. 's': lambda r: partial(spin, int(r)),
  27. 'x': lambda r: partial(exchange, *map(int, r.split('/'))),
  28. 'p': lambda r: partial(partner, *r.split('/'))
  29. }
  30. with open('data/16.txt', 'r') as file:
  31. # Pre-parse the list of moves into function calls to save string-fiddling lots of times
  32. moves = list(map(lambda line: instructions[line[0]](line[1:]), file.readline().strip().split(',')))
  33. print(f'Part one: {dance(1, moves)}')
  34. print(f'Part two: {dance(1000000000, moves)}')