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.

преди 1 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import collections
  2. import itertools
  3. import re
  4. def part1(H):
  5. """
  6. 2 variables, 2 equations
  7. px1 + vx1 * t1 == px2 + vx2 * t2
  8. py1 + vy1 * t1 == py2 + vy2 * t2
  9. t1 = (px2 - px1) / vx1 + (vx2 / vx1) * t2
  10. t1 = (py2 - py1) / vy1 + (vy2 / vy1) * t2
  11. (px2 - px1) / vx1 - (py2 - py1) / vy1 = (vy2 / vy1 - vx2 / vx1) * t2
  12. t2 = c1 / c2
  13. c1 = (px2 - px1) / vx1 - (py2 - py1) / vy1
  14. c2 = (vy2 / vy1 - vx2 / vx1)
  15. """
  16. n = 0
  17. lo, hi = (7, 27) if len(H) < 100 else (2e14, 4e14)
  18. for aa, bb in itertools.combinations(H, 2):
  19. px1, py1, pz1, vx1, vy1, vz1 = aa
  20. px2, py2, pz2, vx2, vy2, vz2 = bb
  21. c1 = (px2 - px1) / vx1 - (py2 - py1) / vy1
  22. c2 = (vy2 / vy1 - vx2 / vx1)
  23. if c2 == 0: continue
  24. t2 = (c1 / c2)
  25. t1 = (px2 - px1) / vx1 + (vx2 / vx1) * t2
  26. if t1 <= 0 or t2 <= 0: continue
  27. if not lo < px1 + vx1 * t1 < hi: continue
  28. if not lo < py1 + vy1 * t1 < hi: continue
  29. if not lo < px2 + vx2 * t2 < hi: continue
  30. if not lo < py2 + vy2 * t2 < hi: continue
  31. n += 1
  32. return n
  33. def part2(H):
  34. """
  35. 6 + t variables, 3 * t equations
  36. """
  37. try:
  38. import z3
  39. except:
  40. return 'Need z3-solver'
  41. Q = {k: z3.Real(k) for k in 'px py pz vx vy vz t0 t1 t2'.split()}
  42. solver = z3.Solver()
  43. solver.add(H[0].px + H[0].vx * Q['t0'] == Q['px'] + Q['vx'] * Q['t0'])
  44. solver.add(H[0].py + H[0].vy * Q['t0'] == Q['py'] + Q['vy'] * Q['t0'])
  45. solver.add(H[0].pz + H[0].vz * Q['t0'] == Q['pz'] + Q['vz'] * Q['t0'])
  46. solver.add(H[1].px + H[1].vx * Q['t1'] == Q['px'] + Q['vx'] * Q['t1'])
  47. solver.add(H[1].py + H[1].vy * Q['t1'] == Q['py'] + Q['vy'] * Q['t1'])
  48. solver.add(H[1].pz + H[1].vz * Q['t1'] == Q['pz'] + Q['vz'] * Q['t1'])
  49. solver.add(H[2].px + H[2].vx * Q['t2'] == Q['px'] + Q['vx'] * Q['t2'])
  50. solver.add(H[2].py + H[2].vy * Q['t2'] == Q['py'] + Q['vy'] * Q['t2'])
  51. solver.add(H[2].pz + H[2].vz * Q['t2'] == Q['pz'] + Q['vz'] * Q['t2'])
  52. solver.check()
  53. model = solver.model()
  54. return model.eval(Q['px'] + Q['py'] + Q['pz'])
  55. text = open(0).read()
  56. Hail = collections.namedtuple('Hail', 'px py pz vx vy vz')
  57. H = [Hail(*[int(n) for n in re.findall(r'-?\d+', line)]) for line in text.splitlines()]
  58. print(part1(H))
  59. print(part2(H))