208 lines
7.2 KiB
C
208 lines
7.2 KiB
C
|
|
#include <stdio.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
#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);
|
||
|
|
}
|