This repository has been archived by the owner on Jan 2, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
day06.nim
91 lines (74 loc) · 2.85 KB
/
day06.nim
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import math, sequtils, strutils
type
Point = array[2, int]
func read_coords(text: string): seq[Point] =
for line in text.strip.splitlines:
let parts = line.split(", ").map(parseInt)
result &= [parts[0], parts[1]]
func bounds(coords: seq[Point]): array[4, int] =
let
xs = coords.map(proc(coord: Point): int = coord[0])
ys = coords.map(proc(coord: Point): int = coord[1])
result = [min(xs), max(xs), min(ys), max(ys)]
func distance(point1: Point, point2: Point): int =
abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])
func nearest(coords: seq[Point], point: Point): int =
let
distances = coords.map(proc(coord: Point): int = coord.distance(point))
lowest = min(distances)
lowest_count = distances.filter(proc (distance: int): bool = distance == lowest).len
if lowest_count == 1:
distances.find(lowest)
else:
-1
func inrange(coords: seq[Point], point: Point): bool =
var sum: int
for coord in coords:
sum += coord.distance(point)
if sum >= 10000: return false
return true
func part1(coords: seq[Point], extents: array[4, int]): int =
var counts = newSeqWith(coords.len, 0)
for x in extents[0] .. extents[1]:
for y in extents[2] .. extents[3]:
let coord = coords.nearest([x, y])
if coord != -1 and counts[coord] > -1:
counts[coord].inc
# If the area reaches the edge of the grid, it will continue infinitely.
# Mark that area as excluded.
if x == extents[0] or x == extents[1] or y == extents[2] or y == extents[3]:
counts[coord] = -1
counts.max
func part2(coords: seq[Point], extents: array[4, int]): int =
var
size = 0
found = false
let
extension = int(10000 / coords.len)
y_start = extents[2] - extension
y_finish = extents[3] + extension
y_range = y_finish - y_start
# The region we're in is going to be contiguous so once we've found some
# 'safe' areas and subsequently hit a row/column with none in, we can abort
for x in extents[0] - extension .. extents[1] + extension:
var
min_y = int.high
max_y = int.high
for y in y_start .. y_finish:
if coords.inrange([x,y]):
if min_y == int.high:
min_y = y
max_y = y
elif max_y != int.high:
break
if min_y != int.high:
size += abs(max_y - min_y) + 1
found = true
elif found:
break
size
let
coords = read_coords(readFile("data/06.txt"))
extents = coords.bounds
echo part1(coords, extents)
echo part2(coords, extents)