main.py 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import os, sys, re
  2. task_dir = os.path.dirname(__file__)
  3. sys.path.append(f"{task_dir}/..")
  4. from get_tasks import get_input, generate_readme, check_example, bench
  5. from math import floor, ceil
  6. def explodes(strl, v=False):
  7. for pair in re.finditer(r"\[(\d+),(\d+)\]", strl):
  8. sd, ed = pair.start(), pair.end()
  9. if strl[:sd].count("[") - strl[:sd].count("]") >= 4:
  10. p1, p2 = int(pair.group(1)), int(pair.group(2))
  11. numreplace = list(re.finditer(r"\d+", strl[:sd]))[::-1]
  12. if numreplace:
  13. s, e, v = (
  14. numreplace[0].start(),
  15. numreplace[0].end(),
  16. int(numreplace[0][0]),
  17. )
  18. before = strl[:s] + str(p1 + v) + strl[e:sd]
  19. else:
  20. before = strl[:sd]
  21. numreplace = list(re.finditer(r"\d+", strl[ed:]))
  22. if numreplace:
  23. s, e, v = (
  24. numreplace[0].start(),
  25. numreplace[0].end(),
  26. int(numreplace[0][0]),
  27. )
  28. after = strl[ed : ed + s] + str(p2 + v) + strl[ed + e :]
  29. else:
  30. after = strl[ed:]
  31. return before + "0" + after, True
  32. return strl, False
  33. def split(strl):
  34. for num in re.finditer(r"\d{2}", strl):
  35. s, e = num.start(), num.end()
  36. d = int(num[0])
  37. ls = floor(d / 2)
  38. rs = ceil(d / 2)
  39. return strl[:s] + f"[{ls},{rs}]" + strl[e:], True
  40. return strl, False
  41. def addition(l):
  42. e = True
  43. while e:
  44. l, e = explodes(l)
  45. if not e:
  46. l, e = split(l)
  47. return l
  48. def magnitude(line):
  49. while pairs := list(re.finditer(r"\[(\d+),(\d+)\]", line)):
  50. for pair in pairs[::-1]:
  51. sd, ed = pair.start(), pair.end()
  52. p1, p2 = int(pair[1]), int(pair[2])
  53. line = line[:sd] + str(p1 * 3 + p2 * 2) + line[ed:]
  54. return int(line)
  55. @bench
  56. def part1(input):
  57. res = []
  58. for line in input:
  59. res.append(line)
  60. if len(res) > 1:
  61. res.append(addition(f"[{res.pop(0)},{res.pop(0)}]"))
  62. print(magnitude(res[0]))
  63. @bench
  64. def part2(input):
  65. mag = []
  66. for ind, line in enumerate(input):
  67. for ind2, line2 in enumerate(input):
  68. if ind == ind2:
  69. continue
  70. mag.append(magnitude(addition(f"[{line},{line2}]")))
  71. print(max(mag))
  72. if __name__ == "__main__":
  73. input, example = get_input(task_dir, 18)
  74. part1(input)
  75. part2(input)
  76. generate_readme(task_dir, 18)