import argparse from typing import List, Set, NamedTuple import pprint import functools import math class Point(NamedTuple): x: int y: int parser = argparse.ArgumentParser() parser.add_argument("ifile", type=argparse.FileType('r')) args = parser.parse_args() lines = [line.strip() for line in args.ifile.readlines()] # for some reason I can't just do `for (x, y) in thing.split(',')` # dunno why. works in the repl. line_segments = [[ Point(int(thing.split(',')[0]), int(thing.split(',')[1])) for thing in line.split(' ')[::2] ] for line in lines] max_x = max(map(lambda p: p.x, [point for segment in line_segments for point in segment])) max_y = max(map(lambda p: p.y, [point for segment in line_segments for point in segment])) board = [[0 for _ in range(0, max_x + 1)] for _ in range(0, max_y + 1)] def draw_line(board: List[List[int]], segment: List[Point]): start, end = segment delta_x = end.x - start.x delta_y = end.y - start.y sign_x = int(math.copysign(1, end.x - start.x)) if abs(delta_x) > 0 else 0 sign_y = int(math.copysign(1, end.y - start.y)) if abs(delta_y) > 0 else 0 for d in range(0, max(abs(delta_x), abs(delta_y)) + 1): board[start.y + sign_y * d][start.x + sign_x * d] += 1 return board finished_board = functools.reduce(draw_line, line_segments, board) print(functools.reduce(lambda acc, val: acc + 1 if val >= 2 else acc, [val for row in finished_board for val in row], 0))