summaryrefslogtreecommitdiff
path: root/15.c
diff options
context:
space:
mode:
Diffstat (limited to '15.c')
-rw-r--r--15.c134
1 files changed, 103 insertions, 31 deletions
diff --git a/15.c b/15.c
index 9e9f70c..b9275a2 100644
--- a/15.c
+++ b/15.c
@@ -42,18 +42,51 @@ sensor_isbeacon(struct sensor const * s, long x, long y)
}
+long
+beacon_frequency(long x, long y)
+{
+ return x * 4000000 + y;
+}
+
+
int
main(int argc, char ** argv)
{
+ int part = 1;
regex_t coords;
+ regmatch_t xy[5];
char buf[BUFSIZ];
struct sensor * sensors = NULL, * s;
int nsensors = 0, i;
- long xmin, xmax, ymin, ymax, zone;
+ long xmin = LONG_MIN, xmax = LONG_MAX, ymin = LONG_MIN, ymax = LONG_MAX, zone;
long x, y = LONG_MIN, empty = 0;
- while ((i = getopt(argc, argv, "y:")) != -1) {
+ while ((i = getopt(argc, argv, "p:l:y:")) != -1) {
switch (i) {
+ case 'p':
+ part = atoi(optarg);
+ break;
+
+ case 'l':
+ if (regcomp(&coords, "(-?[[:digit:]]+),(-?[[:digit:]]+)"
+ ":(-?[[:digit:]]+),(-?[[:digit:]]+)",
+ REG_EXTENDED) != 0)
+ {
+ fprintf(stderr, "Bad regex\n");
+ return -1;
+ }
+ if (regexec(&coords, optarg, arrlen(xy), xy, 0) != 0) {
+ fprintf(stderr, "Bad limit: \"-l x,y:x,y\"\n");
+ regfree(&coords);
+ return -1;
+ }
+ xmin = atol(optarg + xy[1].rm_so);
+ ymin = atol(optarg + xy[2].rm_so);
+ xmax = atol(optarg + xy[3].rm_so);
+ ymax = atol(optarg + xy[4].rm_so);
+ regfree(&coords);
+ break;
+
case 'y':
y = atol(optarg);
break;
@@ -63,11 +96,6 @@ main(int argc, char ** argv)
}
}
- if (y == LONG_MIN) {
- fprintf(stderr, "Required option: y\n");
- return -1;
- }
-
if (regcomp(&coords, "Sensor at x=(-?[[:digit:]]+), y=(-?[[:digit:]]+):"
" closest beacon is at x=(-?[[:digit:]]+), y=(-?[[:digit:]]+)",
REG_EXTENDED) != 0)
@@ -78,7 +106,6 @@ main(int argc, char ** argv)
// Read the sensors and their beacons
while (fgets(buf, sizeof(buf), stdin)) {
- regmatch_t xy[5];
void * p;
if (regexec(&coords, buf, arrlen(xy), xy, 0) != 0) {
@@ -100,35 +127,80 @@ main(int argc, char ** argv)
sensors[nsensors - 1].beacony = atol(buf + xy[4].rm_so);
}
- // Calculate max bounds for sensors/beacons
- s = sensors;
- zone = sensor_zone(s);
- xmin = s->x - zone;
- xmax = s->x + zone;
- ymin = s->y - zone;
- ymax = s->y + zone;
- for (s = sensors + 1; s < sensors + nsensors; ++s) {
+ // Check for spots without beacons
+ if (part == 1) {
+ if (y == LONG_MIN) {
+ fprintf(stderr, "Required option (row): \"-y row\"\n");
+ free(sensors);
+ regfree(&coords);
+ return -1;
+ }
+
+ // Calculate max bounds for sensors/beacons
+ s = sensors;
zone = sensor_zone(s);
- xmin = min(xmin, s->x - zone);
- xmax = max(xmax, s->x + zone);
- ymin = min(ymin, s->y - zone);
- ymax = max(ymax, s->y + zone);
- }
+ xmin = s->x - zone;
+ xmax = s->x + zone;
+ ymin = s->y - zone;
+ ymax = s->y + zone;
+ for (s = sensors + 1; s < sensors + nsensors; ++s) {
+ zone = sensor_zone(s);
+ xmin = min(xmin, s->x - zone);
+ xmax = max(xmax, s->x + zone);
+ ymin = min(ymin, s->y - zone);
+ ymax = max(ymax, s->y + zone);
+ }
- // Check for spots without beacons
- for (x = xmin; x <= xmax; ++x) {
- for (s = sensors; s < sensors + nsensors; ++s) {
- if (sensor_distance(s, x, y) <= sensor_zone(s)
- && !sensor_isbeacon(s, x, y))
- {
- break;
+ // Count positions that cannot be beacons
+ for (x = xmin; x <= xmax; ++x) {
+ for (s = sensors; s < sensors + nsensors; ++s) {
+ if (sensor_distance(s, x, y) <= sensor_zone(s)
+ && !sensor_isbeacon(s, x, y))
+ {
+ break;
+ }
}
+ if (s < sensors + nsensors)
+ ++empty;
}
- if (s < sensors + nsensors)
- ++empty;
+
+ printf("Positions without a beacon on row %ld: %ld\n", y, empty);
}
+ else if (part == 2) {
+ if (ymin == LONG_MIN) {
+ fprintf(stderr, "Required option (limit): \"-l x,y:x,y\"\n");
+ free(sensors);
+ regfree(&coords);
+ return -1;
+ }
- printf("Positions without a beacon on row %ld: %ld\n", y, empty);
+ // Find positions that are not in any sensor zone
+ for (y = ymin; y <= ymax; ++y) {
+ for (x = xmin; x <= xmax; ++x) {
+ for (s = sensors; s < sensors + nsensors; ++s) {
+ zone = sensor_zone(s);
+ if (sensor_distance(s, x, y) <= zone)
+ break;
+ }
+ if (s < sensors + nsensors) {
+ // In a zone. Skip to the end of this sensors zone on this row
+ long end = s->x + zone - labs(s->y - y);
+ if (end > x)
+ x = end;
+ }
+ else {
+ printf("Possible beacon with frequency %ld at %ld,%ld\n",
+ beacon_frequency(x, y), x, y);
+ }
+ }
+ }
+ }
+ else {
+ fprintf(stderr, "Unexpected part: %d\n", part);
+ free(sensors);
+ regfree(&coords);
+ return -1;
+ }
free(sensors);
regfree(&coords);