import std/sets, std/strutils, std/sugar, std/sequtils, std/os type Num = range[0..9999999] Pos = tuple[x, y: Num] Vent = tuple[a, b: Pos] VentType = enum vt_horz vt_vert vt_diag proc parse_pos(pos: string): Pos = let xy = pos.split(',', maxsplit=1).map(parse_int) return (xy[0].Num, xy[1].Num) proc read_vents(filename: string): seq[Vent] = let f = open(filename) defer: f.close() result = collect: for line in f.lines(): let ab = line.split(" -> ", maxsplit=1).map(parse_pos) (ab[0], ab[1]) func classify(v: Vent): VentType = if v.a.x == v.b.x: return vt_vert if v.a.y == v.b.y: return vt_horz return vt_diag iterator intersect(u, v: Vent): Pos = var uc = classify(u) vc = classify(v) if uc == vc: for x in max(u.a.x, v.a.x) .. min(u.b.x, v.b.x): for y in max(u.a.y, v.a.y) .. min(u.b.y, v.b.y): yield (x, y) else: var u = u v = v if uc == vt_vert and vc == vt_horz: (u, v) = (v, u) let x = v.a.x y = u.a.y if x >= u.a.x and x <= u.b.x and y >= v.a.y and y <= v.b.y: yield (x, y) func normalise(v: Vent): Vent = result = v if ((classify(v) != vt_vert and v.b.x < v.a.x) or (classify(v) == vt_vert and v.b.y < v.a.y)): result = (v.b, v.a) proc part1(vents: seq[Vent]): int = var intersections: HashSet[Pos] for i, a in vents: if classify(a) == vt_diag: continue let a = normalise(a) for b in vents[i + 1 .. ^1]: if classify(b) == vt_diag: continue let b = normalise(b) for p in intersect(a, b): intersections.incl(p) return len(intersections) when is_main_module: var filename: string = "5.in" if param_count() == 1: filename = param_str(1) let vents = read_vents(filename) echo part1(vents)