You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
4.1 KiB
152 lines
4.1 KiB
6 years ago
|
#include <stdio.h>
|
||
|
|
||
|
#include <glib.h>
|
||
|
|
||
|
struct coord {
|
||
|
int x;
|
||
|
int y;
|
||
|
};
|
||
|
|
||
|
struct rect {
|
||
|
int x;
|
||
|
int y;
|
||
|
int w;
|
||
|
int h;
|
||
|
};
|
||
|
|
||
|
struct coord *parse_coords(const char *fname, unsigned *len)
|
||
|
{
|
||
|
FILE *f = fopen(fname, "r");
|
||
|
if (!f) {
|
||
|
perror(fname);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
GArray *array = g_array_new(FALSE, FALSE, sizeof(struct coord));
|
||
|
*len = 0;
|
||
|
|
||
|
char *line = NULL;
|
||
|
size_t line_len = 0;
|
||
|
while (getline(&line, &line_len, f) != -1) {
|
||
|
struct coord coord = {0};
|
||
|
if (sscanf(line, "%d, %d", &coord.x, &coord.y) != 2) continue;
|
||
|
g_array_append_val(array, coord);
|
||
|
(*len)++;
|
||
|
}
|
||
|
|
||
|
free(line);
|
||
|
fclose(f);
|
||
|
struct coord *res = (struct coord *)g_array_free(array, FALSE);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
struct rect find_limit(struct coord *coords, unsigned len)
|
||
|
{
|
||
|
struct rect rect = {0};
|
||
|
if (!len) return rect;
|
||
|
|
||
|
int xmax = rect.x = coords->x;
|
||
|
int ymax = rect.y = coords->y;
|
||
|
|
||
|
for (struct coord *coord = coords + 1; coord < coords + len; coord++) {
|
||
|
if (coord->x < rect.x) rect.x = coord->x;
|
||
|
if (coord->y < rect.y) rect.y = coord->y;
|
||
|
if (coord->x > xmax) xmax = coord->x;
|
||
|
if (coord->y > ymax) ymax = coord->y;
|
||
|
}
|
||
|
|
||
|
rect.w = xmax - rect.x + 1;
|
||
|
rect.h = ymax - rect.y + 1;
|
||
|
|
||
|
return rect;
|
||
|
}
|
||
|
|
||
|
unsigned *count_influence(struct coord *coords, unsigned coords_len, struct rect area)
|
||
|
{
|
||
|
unsigned *tally = g_new0(unsigned, coords_len);
|
||
|
|
||
|
for (int y = area.y; y < area.y + area.h; y++) {
|
||
|
for (int x = area.x; x < area.x + area.w; x++) {
|
||
|
unsigned tile = 0;
|
||
|
unsigned shortest = area.h * area.w;
|
||
|
|
||
|
// Find the point with the shortest distance
|
||
|
for (unsigned i = 0; i < coords_len && shortest; i++) {
|
||
|
unsigned dist = abs(coords[i].x - x) + abs(coords[i].y - y);
|
||
|
if (dist < shortest) {
|
||
|
shortest = dist;
|
||
|
tile = i + 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!tile) continue;
|
||
|
|
||
|
// Look for another point with the same distance
|
||
|
for (unsigned i = 0; i < coords_len && shortest; i++) {
|
||
|
unsigned dist = abs(coords[i].x - x) + abs(coords[i].y - y);
|
||
|
if (tile - 1 == i) continue;
|
||
|
if (dist == shortest) {
|
||
|
tile = 0;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//printf("%c", tile ? 'a' + tile - 1 : '.');
|
||
|
if (!tile) continue;
|
||
|
if (tally[tile - 1] < UINT_MAX) tally[tile - 1]++;
|
||
|
}
|
||
|
//printf("\n");
|
||
|
}
|
||
|
|
||
|
return tally;
|
||
|
}
|
||
|
|
||
|
int main()
|
||
|
{
|
||
|
unsigned coords_len;
|
||
|
struct coord *coords = parse_coords("input", &coords_len);
|
||
|
if (!coords) return 1;
|
||
|
|
||
|
/*
|
||
|
* NOTE: This method I'm using to figure our the biggest non-infinite
|
||
|
* influence range for a coordinate is suboptimal and won't work for all inputs.
|
||
|
* I could try to figure out how to calcluate it properly or a better algorithm
|
||
|
* than checking literally each tile in a defined area, but I'm too lazy.
|
||
|
* If it works for my input it's fine ;)
|
||
|
*/
|
||
|
|
||
|
struct rect limit = find_limit(coords, coords_len);
|
||
|
printf("%d,%d\n%d,%d\n",
|
||
|
limit.x, limit.y,
|
||
|
limit.x + limit.w - 1, limit.y + limit.h - 1);
|
||
|
|
||
|
unsigned *tally = count_influence(coords, coords_len, limit);
|
||
|
|
||
|
// Disqualify any coords that don't compete with anything.
|
||
|
for (unsigned a = 0; a < coords_len; a++) {
|
||
|
int north = 0;
|
||
|
int south = 0;
|
||
|
int east = 0;
|
||
|
int west = 0;
|
||
|
for (unsigned b = 0; b < coords_len; b++) {
|
||
|
if (coords[b].y < coords[a].y) north = 1;
|
||
|
if (coords[b].y > coords[a].y) south = 1;
|
||
|
if (coords[b].x > coords[a].x) east = 1;
|
||
|
if (coords[b].x < coords[a].x) west = 1;
|
||
|
}
|
||
|
if (!north || !south || !east || !west) tally[a] = 0;
|
||
|
}
|
||
|
|
||
|
// Find the largest
|
||
|
unsigned largest = 0;
|
||
|
for (unsigned *i = tally; i < tally + coords_len; i++) {
|
||
|
if (*i > largest) largest = *i;
|
||
|
}
|
||
|
|
||
|
printf("Largest: %u\n", largest);
|
||
|
|
||
|
g_free(tally);
|
||
|
g_free(coords);
|
||
|
return 0;
|
||
|
}
|