20_particles.py 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. #!/usr/bin/env python3
  2. import sys
  3. import re
  4. def parse(f):
  5. p, v, a = [], [], []
  6. for line in f:
  7. nums = list(map(int, re.findall(r'-?[0-9]+', line)))
  8. p += nums[:3]
  9. v += nums[3:6]
  10. a += nums[6:]
  11. return p, v, a
  12. def closest_after_steps(p, v, a, steps):
  13. p = p.copy()
  14. v = v.copy()
  15. for step in range(steps):
  16. for i in range(len(p)):
  17. v[i] += a[i]
  18. p[i] += v[i]
  19. p = list(map(abs, p))
  20. d = [sum(p[i:i + 3]) for i in range(0, len(p), 3)]
  21. return d.index(min(d))
  22. def not_collided_after_steps(p, v, a, steps):
  23. p = p.copy()
  24. v = v.copy()
  25. collided = [False] * len(p)
  26. for step in range(steps):
  27. for i in range(len(p)):
  28. if not collided[i]:
  29. v[i] += a[i]
  30. p[i] += v[i]
  31. seen = {}
  32. for i in range(0, len(p), 3):
  33. if not collided[i]:
  34. pos = tuple(p[i:i + 3])
  35. seen.setdefault(pos, []).append(i)
  36. for indices in seen.values():
  37. if len(indices) > 1:
  38. for i in indices:
  39. collided[i] = True
  40. collided[i + 1] = True
  41. collided[i + 2] = True
  42. return collided.count(False) // 3
  43. # part 1
  44. p, v, a = parse(sys.stdin)
  45. print(closest_after_steps(p, v, a, 500))
  46. # part 2
  47. print(not_collided_after_steps(p, v, a, 500))