#include #include #include #define BUFFER_SIZE 512 #define MAX_ROCK_NUMBER 16*1024 #define FLOOR_OFFSET 2 #define EDGE_BUFFER 256 #define min(a, b) (a <= b ? a : b) #define max(a, b) (a >= b ? a : b) // Use this setting to switch between task 1 and task 2 #define ENABLE_FLOOR 1 typedef struct point { int x; int y; } POINT; void buildPath(POINT, POINT, POINT*, int*); POINT nextFall(int, int *[*], POINT); int main() { char buf[BUFFER_SIZE], *p, c; memset(buf, 0, BUFFER_SIZE); p = buf; POINT bedrock[MAX_ROCK_NUMBER], prev, curr; int bedrock_count = 0; int maxX = 0, maxY = 0, x, y; // Read input while ((c = getchar()) != EOF) { *p++ = c; if (c == '\n') { p = buf; sscanf(p, "%i,%i", &x, &y); prev.x = x; prev.y = y; while (*p++ != ' ') {} while(*p != 0) { sscanf(p, "-> %i,%i", &x, &y); if (x > maxX) maxX = x; if (y > maxY) maxY = y; curr.x = x; curr.y = y; buildPath(prev, curr, bedrock, &bedrock_count); prev.x = x; prev.y = y; while (*p++ != ' ') {} while (*p != ' ' && *p != 0) p++; p++; } memset(buf, 0, BUFFER_SIZE); p = buf; } } POINT source = { .x = 500, .y = 0 }, sand; // Allocate memory for the map int **map = (int**)malloc((maxX + 1 + EDGE_BUFFER) * sizeof(int*)); for (int i = 0; i < maxX + 1 + EDGE_BUFFER; i++) { map[i] = (int*)malloc((maxY + FLOOR_OFFSET) * sizeof(int)); memset(map[i], 0, (maxY + FLOOR_OFFSET) * sizeof(int)); } // Fill in the map with bedrock for (int i = 0; i < bedrock_count; i++) { map[bedrock[i].x][bedrock[i].y] = 1; } int fallthrough = 0, sum = 0; POINT fallPosition; // Play until sand falls through while (!fallthrough) { // Simulate each sand sand.x = source.x; sand.y = source.y; do { fallPosition = nextFall(maxY + FLOOR_OFFSET, map, sand); // We fell through the map if (fallPosition.x == -2) { fallthrough = 1; break; } // We hit bedrock if (fallPosition.x == -1) { sum += 1; map[sand.x][sand.y] = 2; // Source gets clogged if (sand.x == source.x && sand.y == source.y) { fallthrough = 1; } } sand = fallPosition; } while(fallPosition.x != -1); } printf("%i\n", sum); } void buildPath(POINT prev, POINT curr, POINT* bedrock, int* bedrock_count) { if (prev.x != curr.x) { for (int i = min(prev.x, curr.x); i <= max(prev.x, curr.x); i++) { bedrock[*bedrock_count].x = i; bedrock[*bedrock_count].y = prev.y; (*bedrock_count)++; } } else if (prev.y != curr.y) { for (int i = min(prev.y, curr.y); i <= max(prev.y, curr.y); i++) { bedrock[*bedrock_count].x = prev.x; bedrock[*bedrock_count].y = i; (*bedrock_count)++; } } } POINT nextFall(int mapHeight, int *map[mapHeight], POINT point) { POINT end = { .x = -1, .y = -1 }; if (point.y == mapHeight - FLOOR_OFFSET && !ENABLE_FLOOR) { // Fall out of the map end.x = -2; end.y = -2; } else if (ENABLE_FLOOR && point.y == mapHeight - 1) { // Fall on floor } else if (map[point.x][point.y+1] == 0) { // Fall straight down end.x = point.x; end.y = point.y + 1; } else if (map[point.x - 1][point.y + 1] == 0) { // Fall left down end.x = point.x - 1; end.y = point.y + 1; } else if (map[point.x + 1][point.y + 1] == 0) { // Fall right down end.x = point.x + 1; end.y = point.y + 1; } return end; }