1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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)
|