Day15
This commit is contained in:
BIN
day15/beacon
Executable file
BIN
day15/beacon
Executable file
Binary file not shown.
229
day15/beacon.c
Normal file
229
day15/beacon.c
Normal file
@@ -0,0 +1,229 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define BUFFER_SIZE 128
|
||||
#define MAX_SENSORS 128
|
||||
#define MAX_RANGES 128
|
||||
#define Y_ROW 2000000L
|
||||
#define MIN_YPOS 0L
|
||||
#define MAX_YPOS 4000000L
|
||||
#define XTUNING 4000000ULL
|
||||
|
||||
#define max(a,b) (a >= b ? a : b)
|
||||
#define min(a,b) (a <= b ? a : b)
|
||||
#define abs(v) ((v) < 0 ? (-1) * (v) : (v))
|
||||
|
||||
typedef struct sensor {
|
||||
long x;
|
||||
long y;
|
||||
long beaconX;
|
||||
long beaconY;
|
||||
long radius;
|
||||
} SENSOR;
|
||||
|
||||
long dist(long, long, long, long);
|
||||
int exists(long [], int, long);
|
||||
unsigned overlap(long, long, long, long);
|
||||
|
||||
int main() {
|
||||
char buf[BUFFER_SIZE], *p, c;
|
||||
memset(buf, 0, BUFFER_SIZE);
|
||||
p = buf;
|
||||
SENSOR sensors[MAX_SENSORS], tmp;
|
||||
int sensor_count = 0;
|
||||
|
||||
while ((c = getchar()) != EOF) {
|
||||
*p++ = c;
|
||||
if (c == '\n') {
|
||||
sscanf(buf, "Sensor at x=%li, y=%li: closest beacon is at x=%li, y=%li", &tmp.x, &tmp.y, &tmp.beaconX, &tmp.beaconY);
|
||||
tmp.radius = dist(tmp.x, tmp.y, tmp.beaconX, tmp.beaconY);
|
||||
sensors[sensor_count] = tmp;
|
||||
sensor_count++;
|
||||
memset(buf, 0, BUFFER_SIZE);
|
||||
p = buf;
|
||||
}
|
||||
}
|
||||
|
||||
// Scan every row in the given territory
|
||||
for (long jk = MIN_YPOS; jk < MAX_YPOS; jk++) {
|
||||
// Save the range for each sensor
|
||||
long (*scanned)[2];
|
||||
scanned = (long(*)[2])malloc(sensor_count * sizeof(long[2]));
|
||||
memset(scanned, 0, sensor_count * sizeof(long[2]));
|
||||
unsigned sum = 0;
|
||||
|
||||
// Find all scanned in y=jk
|
||||
for (int i = 0; i < sensor_count; i++) {
|
||||
// Not in range
|
||||
if (abs(sensors[i].y - jk) > sensors[i].radius) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned tmp = (sensors[i].radius - abs(sensors[i].y - jk));
|
||||
scanned[i][0] = sensors[i].x - tmp;
|
||||
scanned[i][1] = sensors[i].x + tmp;
|
||||
}
|
||||
|
||||
long (*ranges)[2];
|
||||
ranges = (long(*)[2])malloc(MAX_RANGES * sizeof(long[2]));
|
||||
memset(ranges, 0, MAX_RANGES * sizeof(long[2]));
|
||||
int range_count = 0;
|
||||
// Count scanned and remove overlaps
|
||||
for (int i = 0; i < sensor_count; i++) {
|
||||
long sections[16][2];
|
||||
int section_count = 0;
|
||||
sections[0][0] = scanned[i][0];
|
||||
sections[0][1] = scanned[i][1];
|
||||
section_count++;
|
||||
for (int j = 0; j < range_count; j++) {
|
||||
for (int k = 0; k < section_count; k++) {
|
||||
// Not overlapping
|
||||
if (sections[k][0] > ranges[j][1] || sections[k][1] < ranges[j][0]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// fully covered
|
||||
else if (sections[k][0] >= ranges[j][0] && sections[k][1] <= ranges[j][1]) {
|
||||
for (int l = k; l < section_count - 1; l++) {
|
||||
sections[l][0] = sections[l+1][0];
|
||||
sections[l][1] = sections[l+1][1];
|
||||
}
|
||||
section_count--;
|
||||
break;
|
||||
}
|
||||
|
||||
// Inverse covered splits section to two
|
||||
else if (sections[k][0] < ranges[j][0] && sections[k][1] > ranges[j][1]) {
|
||||
// Push everything forward
|
||||
for (int l = section_count; l > k + 1; l--) {
|
||||
sections[l][0] = sections[l-1][0];
|
||||
sections[l][1] = sections[l-1][1];
|
||||
}
|
||||
section_count++;
|
||||
sections[k+1][1] = sections[k][1];
|
||||
sections[k][1] = ranges[j][0] - 1;
|
||||
sections[k+1][0] = ranges[j][1] + 1;
|
||||
}
|
||||
|
||||
// Left hook
|
||||
else if (sections[k][0] < ranges[j][0] && sections[k][1] <= ranges[j][1]) {
|
||||
sections[k][1] = ranges[j][0] - 1;
|
||||
}
|
||||
|
||||
// Right hook
|
||||
else if (sections[k][0] >= ranges[j][0] && sections[k][1] > ranges[j][1]) {
|
||||
sections[k][0] = ranges[j][1] + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < section_count; j++) {
|
||||
ranges[range_count][0] = sections[j][0];
|
||||
ranges[range_count][1] = sections[j][1];
|
||||
range_count++;
|
||||
}
|
||||
}
|
||||
|
||||
//printf("OPOPOP\n");
|
||||
|
||||
int changeCount = 0;
|
||||
// Combine ranges
|
||||
do {
|
||||
changeCount = 0;
|
||||
for (int i = 0; i < range_count; i++) {
|
||||
for (int j = i + 1; j < range_count; j++) {
|
||||
if (ranges[i][0] == ranges[j][1] + 1) {
|
||||
ranges[i][0] = ranges[j][0];
|
||||
for (int k = j; k < range_count - 1; k++) {
|
||||
ranges[k][0] = ranges[k+1][0];
|
||||
ranges[k][1] = ranges[k+1][1];
|
||||
}
|
||||
range_count--;
|
||||
changeCount++;
|
||||
} else if (ranges[i][1] + 1 == ranges[j][0]) {
|
||||
ranges[i][1] = ranges[j][1];
|
||||
for (int k = j; k < range_count - 1; k++) {
|
||||
ranges[k][0] = ranges[k+1][0];
|
||||
ranges[k][1] = ranges[k+1][1];
|
||||
}
|
||||
range_count--;
|
||||
changeCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (changeCount != 0);
|
||||
|
||||
for (int i = 0; i < range_count; i++) {
|
||||
//printf("[%li,%li]\n", ranges[i][0], ranges[i][1]);
|
||||
sum += ranges[i][1] - ranges[i][0] + 1;
|
||||
}
|
||||
|
||||
// I don't really understand why, but we also have to exclude beacons
|
||||
long beaconInWay[32];
|
||||
int beaconInWayCount = 0;
|
||||
for (int i = 0; i < sensor_count; i++) {
|
||||
int skip = 0;
|
||||
if (sensors[i].beaconY != jk) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int k = 0; k < beaconInWayCount; k++) {
|
||||
if (beaconInWay[k] == sensors[i].beaconX) {
|
||||
skip = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (skip) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < range_count; j++) {
|
||||
if (sensors[i].beaconX >= ranges[j][0] && sensors[i].beaconX <= ranges[j][1]) {
|
||||
beaconInWay[beaconInWayCount] = sensors[i].beaconX;
|
||||
beaconInWayCount++;
|
||||
sum -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally print the results
|
||||
if (jk == Y_ROW) {
|
||||
printf("Part one: %u\n", sum);
|
||||
}
|
||||
|
||||
// Second part
|
||||
for (int i = 0; i < range_count; i++) {
|
||||
if (ranges[i][0] > MIN_YPOS && ranges[i][0] <= MAX_YPOS) {
|
||||
printf("X: %li, Y: %li\n", ranges[i][0] - 1, jk);
|
||||
printf("Second part: %llu\n", (unsigned long long)(ranges[i][0]-1)*XTUNING+(unsigned long long)jk);
|
||||
}
|
||||
}
|
||||
free(scanned);
|
||||
free(ranges);
|
||||
}
|
||||
}
|
||||
|
||||
long dist(long x1, long y1, long x2, long y2) {
|
||||
return abs(x1-x2) + abs(y1-y2);
|
||||
}
|
||||
|
||||
// We could do better if we want speed
|
||||
// But I hope it is enough
|
||||
int exists(long scanned[], int scanned_count, long x) {
|
||||
for (int i = 0; i < scanned_count; i++) {
|
||||
if (scanned[i] == x) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned overlap(long min1, long max1, long min2, long max2) {
|
||||
if (max1 < min2 || max2 < min1)
|
||||
return 0;
|
||||
|
||||
return min(max1, max2) - max(min1, min2) + 1;
|
||||
}
|
||||
27
day15/input.txt
Normal file
27
day15/input.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
Sensor at x=3523437, y=2746095: closest beacon is at x=3546605, y=2721324
|
||||
Sensor at x=282831, y=991087: closest beacon is at x=743030, y=-87472
|
||||
Sensor at x=1473740, y=3283213: closest beacon is at x=1846785, y=3045894
|
||||
Sensor at x=1290563, y=46916: closest beacon is at x=743030, y=-87472
|
||||
Sensor at x=3999451, y=15688: closest beacon is at x=3283637, y=-753607
|
||||
Sensor at x=1139483, y=2716286: closest beacon is at x=1846785, y=3045894
|
||||
Sensor at x=3137614, y=2929987: closest beacon is at x=3392051, y=3245262
|
||||
Sensor at x=2667083, y=2286333: closest beacon is at x=2126582, y=2282363
|
||||
Sensor at x=3699264, y=2920959: closest beacon is at x=3546605, y=2721324
|
||||
Sensor at x=3280991, y=2338486: closest beacon is at x=3546605, y=2721324
|
||||
Sensor at x=833202, y=92320: closest beacon is at x=743030, y=-87472
|
||||
Sensor at x=3961416, y=2485266: closest beacon is at x=3546605, y=2721324
|
||||
Sensor at x=3002132, y=3500345: closest beacon is at x=3392051, y=3245262
|
||||
Sensor at x=2482128, y=2934657: closest beacon is at x=1846785, y=3045894
|
||||
Sensor at x=111006, y=2376713: closest beacon is at x=354526, y=3163958
|
||||
Sensor at x=424237, y=2718408: closest beacon is at x=354526, y=3163958
|
||||
Sensor at x=3954504, y=3606495: closest beacon is at x=3392051, y=3245262
|
||||
Sensor at x=2275050, y=2067292: closest beacon is at x=2333853, y=2000000
|
||||
Sensor at x=1944813, y=2557878: closest beacon is at x=2126582, y=2282363
|
||||
Sensor at x=2227536, y=2152792: closest beacon is at x=2126582, y=2282363
|
||||
Sensor at x=3633714, y=1229193: closest beacon is at x=3546605, y=2721324
|
||||
Sensor at x=1446898, y=1674290: closest beacon is at x=2333853, y=2000000
|
||||
Sensor at x=3713985, y=2744503: closest beacon is at x=3546605, y=2721324
|
||||
Sensor at x=2281504, y=3945638: closest beacon is at x=1846785, y=3045894
|
||||
Sensor at x=822012, y=3898848: closest beacon is at x=354526, y=3163958
|
||||
Sensor at x=89817, y=3512049: closest beacon is at x=354526, y=3163958
|
||||
Sensor at x=2594265, y=638715: closest beacon is at x=2333853, y=2000000
|
||||
Reference in New Issue
Block a user