diff options
author | Tomasz Kramkowski <tk@the-tk.com> | 2021-12-06 23:04:43 +0000 |
---|---|---|
committer | Tomasz Kramkowski <tk@the-tk.com> | 2021-12-06 23:04:43 +0000 |
commit | c45d2e403278608e4c0baef70343e03149d499b3 (patch) | |
tree | 48b5310fb5142fa0ca0acdc8b22935aa8d79bac1 | |
parent | 64ffb0abb536d21aa0225272d4faa22c2abf2070 (diff) | |
download | aoc2021-c45d2e403278608e4c0baef70343e03149d499b3.tar.gz aoc2021-c45d2e403278608e4c0baef70343e03149d499b3.tar.xz aoc2021-c45d2e403278608e4c0baef70343e03149d499b3.zip |
day 5: nim
-rw-r--r-- | d5.nim | 71 |
1 files changed, 71 insertions, 0 deletions
@@ -0,0 +1,71 @@ +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) |