part2.py 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. import argparse
  2. from typing import List, Set, NamedTuple
  3. import pprint
  4. import functools
  5. import math
  6. class Point(NamedTuple):
  7. x: int
  8. y: int
  9. parser = argparse.ArgumentParser()
  10. parser.add_argument("ifile", type=argparse.FileType('r'))
  11. args = parser.parse_args()
  12. lines = [line.strip() for line in args.ifile.readlines()]
  13. # for some reason I can't just do `for (x, y) in thing.split(',')`
  14. # dunno why. works in the repl.
  15. line_segments = [[
  16. Point(int(thing.split(',')[0]), int(thing.split(',')[1])) for thing in line.split(' ')[::2]
  17. ] for line in lines]
  18. max_x = max(map(lambda p: p.x, [point for segment in line_segments for point in segment]))
  19. max_y = max(map(lambda p: p.y, [point for segment in line_segments for point in segment]))
  20. board = [[0 for _ in range(0, max_x + 1)] for _ in range(0, max_y + 1)]
  21. def draw_line(board: List[List[int]], segment: List[Point]):
  22. start, end = segment
  23. delta_x = end.x - start.x
  24. delta_y = end.y - start.y
  25. sign_x = int(math.copysign(1, end.x - start.x)) if abs(delta_x) > 0 else 0
  26. sign_y = int(math.copysign(1, end.y - start.y)) if abs(delta_y) > 0 else 0
  27. for d in range(0, max(abs(delta_x), abs(delta_y)) + 1):
  28. board[start.y + sign_y * d][start.x + sign_x * d] += 1
  29. return board
  30. finished_board = functools.reduce(draw_line, line_segments, board)
  31. print(functools.reduce(lambda acc, val: acc + 1 if val >= 2 else acc, [val for row in finished_board for val in row], 0))