|
@@ -0,0 +1,87 @@
|
|
1
|
+import math, sequtils, strutils
|
|
2
|
+
|
|
3
|
+type
|
|
4
|
+ Point = array[2, int]
|
|
5
|
+
|
|
6
|
+func read_coords(text: string): seq[Point] =
|
|
7
|
+ for line in text.strip.splitlines:
|
|
8
|
+ let parts = line.split(", ").map(parseInt)
|
|
9
|
+ result &= [parts[0], parts[1]]
|
|
10
|
+
|
|
11
|
+func bounds(coords: seq[Point]): array[4, int] =
|
|
12
|
+ let
|
|
13
|
+ xs = coords.map(proc(coord: Point): int = coord[0])
|
|
14
|
+ ys = coords.map(proc(coord: Point): int = coord[1])
|
|
15
|
+ result = [min(xs), max(xs), min(ys), max(ys)]
|
|
16
|
+
|
|
17
|
+func distance(point1: Point, point2: Point): int = abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])
|
|
18
|
+
|
|
19
|
+func nearest(coords: seq[Point], point: Point): int =
|
|
20
|
+ var
|
|
21
|
+ min = -1
|
|
22
|
+ best = -1
|
|
23
|
+ dupe = false
|
|
24
|
+ i = 0
|
|
25
|
+
|
|
26
|
+ for coord in coords:
|
|
27
|
+ let distance = coord.distance(point)
|
|
28
|
+ if min == -1 or distance < min:
|
|
29
|
+ min = distance
|
|
30
|
+ best = i
|
|
31
|
+ dupe = false
|
|
32
|
+ elif min == distance:
|
|
33
|
+ dupe = true
|
|
34
|
+ i += 1
|
|
35
|
+
|
|
36
|
+ if dupe:
|
|
37
|
+ result = -1
|
|
38
|
+ else:
|
|
39
|
+ result = best
|
|
40
|
+
|
|
41
|
+func inrange(coords: seq[Point], point: Point): bool = coords.map(proc (coord: Point): int = coord.distance(point)).sum < 10000
|
|
42
|
+
|
|
43
|
+let
|
|
44
|
+ coords = read_coords(readFile("data/06.txt"))
|
|
45
|
+ extents = coords.bounds
|
|
46
|
+
|
|
47
|
+var
|
|
48
|
+ counts = newSeqWith(coords.len, 0)
|
|
49
|
+ excluded = newSeqWith(coords.len, false)
|
|
50
|
+
|
|
51
|
+for x in extents[0] .. extents[1]:
|
|
52
|
+ for y in extents[2] .. extents[3]:
|
|
53
|
+ let coord = coords.nearest([x, y])
|
|
54
|
+ if coord != -1:
|
|
55
|
+ counts[coord] += 1
|
|
56
|
+ if x == extents[0] or x == extents[1] or y == extents[2] or y == extents[3]:
|
|
57
|
+ excluded[coord] = true
|
|
58
|
+
|
|
59
|
+echo zip(counts, excluded)
|
|
60
|
+ .filter(proc(x: tuple[a: int, b: bool]): bool = not x.b)
|
|
61
|
+ .map(proc(x: tuple[a: int, b: bool]): int = x.a)
|
|
62
|
+ .max
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+var size = 0
|
|
66
|
+let
|
|
67
|
+ extension = int(10000 / coords.len)
|
|
68
|
+ y_start = extents[2] - extension
|
|
69
|
+ y_finish = extents[3] + extension
|
|
70
|
+ y_range = y_finish - y_start
|
|
71
|
+
|
|
72
|
+for x in extents[0] - extension .. extents[1] + extension:
|
|
73
|
+ var
|
|
74
|
+ min_y = 0
|
|
75
|
+ max_y = 0
|
|
76
|
+ for y in extents[2] - extension .. extents[3] + extension:
|
|
77
|
+ if coords.inrange([x,y]):
|
|
78
|
+ min_y = y
|
|
79
|
+ break
|
|
80
|
+ for dy in 0 .. y_range:
|
|
81
|
+ var y = y_finish - dy
|
|
82
|
+ if coords.inrange([x,y]):
|
|
83
|
+ max_y = y + 1
|
|
84
|
+ break
|
|
85
|
+ size += abs(max_y - min_y)
|
|
86
|
+
|
|
87
|
+echo size
|