Files
adventofcode2022/day17/jet.c

208 lines
7.2 KiB
C
Raw Normal View History

2022-12-22 13:20:13 +01:00
#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);
}