#include #include #include #define MAX_JET_PATTERN 16*1024 #define MAX_STATINARY_ROCK_LAYERS 2*1024*1024 #define ROW_WIDTH 7 #define ROCK_TYPE_COUNT 5 #define ROCK_THRESHOLD 1000000000000ULL typedef enum direction { LEFT, RIGHT, } DIRECTION; // Each rock will consist a maximum of 5 elements // The elements array contains relative positions to the refElement // By convention the refElement is always the position that is // the bottom left corner of the rock's enclosing rectangle // (Not always part of the rock itself) // The refElement is used for universal spawning of the rocks typedef struct rock { int element_count; int refElement[2]; int elements[5][2]; } ROCK; int main() { char c; DIRECTION *jetPattern; jetPattern = (DIRECTION*)malloc(MAX_JET_PATTERN * sizeof(DIRECTION)); memset(jetPattern, 0, MAX_JET_PATTERN * sizeof(DIRECTION)); unsigned jetPattern_count = 0, currJet = 0; while ((c = getchar()) != EOF) { switch (c) { case '<': jetPattern[jetPattern_count] = LEFT; break; case '>': jetPattern[jetPattern_count] = RIGHT; break; default: jetPattern_count--; } jetPattern_count++; } // We will store the stationary rocks by row int **rocks = (int**)malloc(MAX_STATINARY_ROCK_LAYERS * sizeof(int*)); for (int i = 0; i < MAX_STATINARY_ROCK_LAYERS; i++) { rocks[i] = (int*)malloc(ROW_WIDTH * sizeof(int)); memset(rocks[i], 0, ROW_WIDTH * sizeof(int)); } // Highest rock layer long highestLayer = -1; // Define every rock type ROCK rockTypes[ROCK_TYPE_COUNT] = { { .element_count = 4, .refElement = {0, 0}, .elements = {{0,0}, {0,1}, {0,2}, {0,3}}}, { .element_count = 5, .refElement = {0, 0}, .elements = {{1,0}, {0,1}, {1,1}, {2,1}, {1,2}}}, { .element_count = 5, .refElement = {0, 0}, .elements = {{0,0}, {0,1}, {0,2}, {1,2}, {2,2}}}, { .element_count = 4, .refElement = {0, 0}, .elements = {{0,0}, {1,0}, {2,0}, {3,0}}}, { .element_count = 4, .refElement = {0, 0}, .elements = {{0,0}, {0,1}, {1,0}, {1,1}}} }; int currentRock = 0; unsigned long long rockBottomCount = 0ULL, cumHighestLayer = 0ULL; while (rockBottomCount != ROCK_THRESHOLD) { // Handle overflow if (currentRock == ROCK_TYPE_COUNT) { currentRock = 0; } // Spawn new rock rockTypes[currentRock].refElement[0] = highestLayer + 4; rockTypes[currentRock].refElement[1] = 2; // Fall int bottom = 0; do { if (currJet == jetPattern_count) { currJet = 0; } // Jet ROCK currentPosition = rockTypes[currentRock]; // Move to jet direction int xdirection = 0; switch (jetPattern[currJet]) { case LEFT: xdirection = -1; break; case RIGHT: xdirection = 1; break; } rockTypes[currentRock].refElement[1] += xdirection; int collision = 0; if (rockTypes[currentRock].refElement[1] == -1) { collision = 1; } if (!collision) { for (int i = 0; i < rockTypes[currentRock].element_count; i++) { if (rockTypes[currentRock].refElement[1] + rockTypes[currentRock].elements[i][1] == ROW_WIDTH) { collision = 1; break; } if (rocks[rockTypes[currentRock].refElement[0]+rockTypes[currentRock].elements[i][0]][rockTypes[currentRock].refElement[1]+rockTypes[currentRock].elements[i][1]]) { collision = 1; break; } } } if (collision) { rockTypes[currentRock] = currentPosition; } collision = 0; // Fall if (rockTypes[currentRock].refElement[0] == 0) { collision = 1; } if (!collision) { for (int i = 0; i < rockTypes[currentRock].element_count; i++) { if (rocks[rockTypes[currentRock].refElement[0]+rockTypes[currentRock].elements[i][0]-1][rockTypes[currentRock].refElement[1]+rockTypes[currentRock].elements[i][1]]) { collision = 1; break; } } } if (collision) { bottom = 1; } else { rockTypes[currentRock].refElement[0]--; } currJet++; } while(!bottom); rockBottomCount++; // Freeze rock for (int i = 0; i < rockTypes[currentRock].element_count; i++) { rocks[rockTypes[currentRock].refElement[0] + rockTypes[currentRock].elements[i][0]][rockTypes[currentRock].refElement[1] + rockTypes[currentRock].elements[i][1]] = 1; if (rockTypes[currentRock].refElement[0] + rockTypes[currentRock].elements[i][0] > highestLayer) { highestLayer = rockTypes[currentRock].refElement[0] + rockTypes[currentRock].elements[i][0]; } } currentRock++; int repeating; // The commented out code below calculates the repeat period (2597) // in rock layers. After that you can get the number of rocks in the // period (1705). It also outputs the offset (302) which can also be // converted to number of rocks (205) if (rockBottomCount == 205) { rockBottomCount += ((ROCK_THRESHOLD-205)/1705)*1705; cumHighestLayer += ((ROCK_THRESHOLD-205)/1705)*2597; } // We have reached our memory limit, we must find the repeating pattern // if (highestLayer >= (MAX_STATINARY_ROCK_LAYERS) - 10) { // for (long long j = 2; j <= MAX_STATINARY_ROCK_LAYERS/32; j++) { // for (long long i = 0; i < j; i++) { // repeating = 1; // for (long long k = 1; k < (MAX_STATINARY_ROCK_LAYERS-i)/j; k++) { // for (long long l = 0; l < j; l++) { // if (memcmp(rocks[i+l], rocks[i+k*j+l], ROW_WIDTH) != 0) { // repeating = 0; // break; // } // } // if (repeating) { // break; // } // } // if (repeating) { // printf("Repeat period: %lli Repeat offset: %lli\n", j, i); // break; // } // } // if (repeating) { // break; // } // } // } // if (repeating) { // break; // } } printf("%llu\n", cumHighestLayer + (unsigned long long)highestLayer + 1ULL); free(jetPattern); for (int i = 0; i < MAX_STATINARY_ROCK_LAYERS; i++) { free(rocks[i]); } free(rocks); }