14_docking.py 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. #!/usr/bin/env python3
  2. import sys
  3. from functools import reduce
  4. from itertools import product
  5. from operator import or_
  6. def parse(f):
  7. x_tr = str.maketrans('X1', '10')
  8. for line in f:
  9. left, right = line.rstrip().split(' = ')
  10. if left == 'mask':
  11. x = int(right.translate(x_tr), 2)
  12. ones = int(right.replace('X', '0'), 2)
  13. yield True, x, ones
  14. else:
  15. yield False, int(left[4:-1]), int(right)
  16. def run_v1(program):
  17. mem = {}
  18. and_mask = or_mask = 0
  19. for is_mask, a, b in program:
  20. if is_mask:
  21. and_mask = a
  22. or_mask = b
  23. else:
  24. mem[a] = b & and_mask | or_mask
  25. return sum(mem.values())
  26. def run_v2(program):
  27. mem = {}
  28. fluct_masks = []
  29. for is_mask, a, b in program:
  30. if is_mask:
  31. and_mask = ~(a | b)
  32. or_mask = b
  33. fl = [i for i in range(36) if a >> i & 1]
  34. fluct_masks = [reduce(or_, (b << i for b, i in zip(bits, fl)), 0)
  35. for bits in product((0, 1), repeat=len(fl))]
  36. else:
  37. for fluct_mask in fluct_masks:
  38. mem[a & and_mask | or_mask | fluct_mask] = b
  39. return sum(mem.values())
  40. program = list(parse(sys.stdin))
  41. print(run_v1(program))
  42. print(run_v2(program))