From dd5bf987e416d249c73f2ef9ae17fa7afea12c5e Mon Sep 17 00:00:00 2001 From: mid-kid Date: Fri, 14 Dec 2018 01:38:40 +0100 Subject: [PATCH] day6p1 --- day6p1/Makefile | 12 ++++ day6p1/input | 50 ++++++++++++++++ day6p1/main.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 213 insertions(+) create mode 100644 day6p1/Makefile create mode 100644 day6p1/input create mode 100644 day6p1/main.c diff --git a/day6p1/Makefile b/day6p1/Makefile new file mode 100644 index 0000000..c711967 --- /dev/null +++ b/day6p1/Makefile @@ -0,0 +1,12 @@ +CFLAGS := -Wall -Wextra -std=c17 -D_GNU_SOURCE + +LIBS := glib-2.0 +CFLAGS += $(shell pkg-config --cflags $(LIBS)) +LDLIBS := $(shell pkg-config --libs $(LIBS)) + +.PHONY: all +all: main + +.PHONY: clean +clean: + rm -f main diff --git a/day6p1/input b/day6p1/input new file mode 100644 index 0000000..3671ecf --- /dev/null +++ b/day6p1/input @@ -0,0 +1,50 @@ +63, 142 +190, 296 +132, 194 +135, 197 +327, 292 +144, 174 +103, 173 +141, 317 +265, 58 +344, 50 +184, 238 +119, 61 +329, 106 +70, 242 +272, 346 +312, 166 +283, 351 +286, 206 +57, 225 +347, 125 +152, 186 +131, 162 +45, 299 +142, 102 +61, 100 +111, 218 +73, 266 +350, 173 +306, 221 +42, 284 +150, 122 +322, 286 +346, 273 +75, 354 +68, 124 +194, 52 +92, 44 +77, 98 +77, 107 +141, 283 +87, 306 +184, 110 +318, 343 +330, 196 +303, 353 +268, 245 +180, 220 +342, 337 +127, 107 +203, 127 diff --git a/day6p1/main.c b/day6p1/main.c new file mode 100644 index 0000000..6cd5a2b --- /dev/null +++ b/day6p1/main.c @@ -0,0 +1,151 @@ +#include + +#include + +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; +}