-
Notifications
You must be signed in to change notification settings - Fork 2
/
06.c
152 lines (123 loc) · 3.46 KB
/
06.c
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include "adventofcode.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define PUZZLE_NAME "Day 6: Chronal Coordinates"
struct Point {
int x;
int y;
};
void determine_bounds(struct Point *points, size_t n, int bounds[4]) {
bounds[0] = points[0].x;
bounds[1] = points[0].y;
bounds[2] = points[0].x;
bounds[3] = points[0].y;
for (size_t i = 1; i < n; i++) {
if (points[i].x < bounds[0]) {
bounds[0] = points[i].x;
} else if (points[i].x > bounds[2]) {
bounds[2] = points[i].x;
}
if (points[i].y < bounds[1]) {
bounds[1] = points[i].y;
} else if (points[i].y > bounds[3]) {
bounds[3] = points[i].y;
}
}
}
static size_t parse(const char *s, struct Point points[static 64], int bounds[4]) {
size_t n = 0;
while (*s != 0x0 && n < 64) {
s = parse_int(&points[n].x, s);
s = skip(", ", s);
s = parse_int(&points[n].y, s);
s = skip_optional('\n', s);
n++;
}
determine_bounds(points, n, bounds);
return n;
}
static int get_closest_point(const struct Point points[static 64], const size_t n, const int x, const int y) {
int closest_idx = -1;
int closest_distance = 1 << 30;
for (size_t p = 0; p < n; p++) {
int distance = abs(x - points[p].x) + abs(y - points[p].y);
if (distance < closest_distance) {
closest_distance = distance;
closest_idx = (int)p;
} else if (distance == closest_distance) {
// if equally low, keep lowest distance but reset index
closest_idx = -1;
}
}
return closest_idx;
}
unsigned int pt1(const struct Point points[static 64], const size_t n, const int bounds[4]) {
assert(n <= 64);
unsigned int areas[64] = {0};
unsigned int infinite[64] = {0};
for (int x = bounds[0], y = bounds[1]; x <= bounds[2] && y <= bounds[3];) {
int closest_idx = get_closest_point(points, n, x, y);
if (closest_idx > -1) {
areas[closest_idx]++;
// if closest point touches any bound
// it's guaranteed to be infinite
if (x == bounds[0] || x == bounds[2] || y == bounds[1] ||
y == bounds[3]) {
infinite[closest_idx] = 1;
}
}
// prepare for next iteration
if (x >= bounds[2]) {
x = bounds[0];
y++;
} else {
x++;
}
}
size_t largest = 0;
for (size_t p = 0; p < n; p++) {
if (areas[p] > areas[largest] && infinite[p] == 0) {
largest = p;
}
}
return areas[largest];
}
unsigned int pt2(const struct Point points[static 64], const size_t n, const int bounds[static 4]) {
assert(n <= 64);
unsigned int count = 0;
for (int x = bounds[0], y = bounds[1]; x <= bounds[2] && y <= bounds[3];) {
int distance = 0;
for (size_t p = 0; p < n && distance < 10000; p++) {
struct Point point = points[p];
distance += (abs(point.x - x) + abs(point.y - y));
}
if (distance < 10000) {
count += 1;
}
// prepare for next iteration
if (x >= bounds[2]) {
x = bounds[0];
y++;
} else {
x++;
}
}
return count;
}
int main(void) {
clock_t t = clock_time();
char input[1024 * 64];
read_input_file(input, 64 * 1024, "06.txt");
int bounds[4];
struct Point points[64];
size_t n = parse(input, points, bounds);
unsigned int a1 = pt1(points, n, bounds);
unsigned int a2 = pt2(points, n, bounds);
printf("--- %s ---\n", PUZZLE_NAME);
printf("Part 1: %d\n", a1);
printf("Part 2: %d\n", a2);
printf("Time: %.2fms\n", clock_time_since(t));
return EXIT_SUCCESS;
}