Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

115 lines
2.8KB

  1. import builtins
  2. import collections
  3. import hashlib
  4. import itertools
  5. import importlib
  6. import math
  7. import os
  8. import re
  9. import string
  10. import sys
  11. from pathlib import Path
  12. import requests
  13. def integers(line):
  14. return [int(n) for n in re.findall(r'\d+', line)]
  15. def lcm(a, b):
  16. return abs(a * b) // math.gcd(a, b)
  17. def render(grid, brush=None):
  18. if brush is None:
  19. brush = {v: v for v in grid.values()}
  20. if isinstance(brush, str):
  21. brush = {i: c for i, c in enumerate(brush)}
  22. xmin, *_, xmax = sorted(int(p.real) for p in grid)
  23. ymin, *_, ymax = sorted(int(p.imag) for p in grid)
  24. brush[None] = ' '
  25. rendered = ''
  26. for y in range(ymin, ymax + 1):
  27. for x in range(xmin, xmax + 1):
  28. rendered += brush[grid.get(complex(x, y))]
  29. rendered += '\n'
  30. return rendered
  31. def read_image(text):
  32. grid = collections.defaultdict(str)
  33. for y, line in enumerate(text.splitlines()):
  34. for x, cell in enumerate(line):
  35. grid[complex(x, y)] = cell
  36. return grid, x + 1, y + 1
  37. def shortest_path(start, end, move):
  38. seen = {}
  39. edge = {start: None}
  40. while edge:
  41. seen.update(edge)
  42. edge = {
  43. adj: pos
  44. for pos in edge
  45. for adj in move(pos)
  46. if adj not in seen
  47. }
  48. if end in seen:
  49. break
  50. else:
  51. raise RuntimeError('Path not found', seen)
  52. path = []
  53. while end:
  54. path.append(end)
  55. end = seen[end]
  56. return path[::-1]
  57. def ensure_data(path):
  58. if not path.exists():
  59. year, qn = map(int, re.findall(r'\d+', sys.argv[1]))
  60. url = f'https://adventofcode.com/{year}/day/{qn}/input'
  61. cookies = {'session': os.environ['SESSION']}
  62. response = requests.get(url, cookies=cookies)
  63. response.raise_for_status()
  64. path.write_bytes(response.content)
  65. def batch(iterable, size):
  66. count = itertools.count()
  67. for _, sub in itertools.groupby(iterable, lambda _: next(count) // size):
  68. yield sub
  69. def md5(string):
  70. return hashlib.md5(string.encode()).hexdigest()
  71. def loop_consume(lines, handler):
  72. instructions = collections.deque(lines)
  73. count = 0
  74. while instructions:
  75. ok = handler(instructions[0])
  76. if ok:
  77. instructions.popleft()
  78. count = 0
  79. elif count < len(instructions):
  80. instructions.rotate(1)
  81. count += 1
  82. else:
  83. raise RuntimeError('Reached steady state')
  84. if __name__ == '__main__':
  85. data_file = Path(sys.argv[1]).with_suffix('.dat')
  86. ensure_data(data_file)
  87. builtins.data_file = data_file
  88. builtins.string = string
  89. builtins.re = re
  90. rel = re.sub(r'.+(y\d+)/(p\d+).+', r'\1.\2', os.environ['FILE'])
  91. mod = importlib.import_module(rel)
  92. print(getattr(mod, 'ans1', None))
  93. print(getattr(mod, 'ans2', None))