summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--d5.nim71
1 files changed, 71 insertions, 0 deletions
diff --git a/d5.nim b/d5.nim
new file mode 100644
index 0000000..5c5e94e
--- /dev/null
+++ b/d5.nim
@@ -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)