#include #include #include #define LINE_MAX 256 int arraySize = 0; char **readSeats(FILE *fp) { char **allSeats = NULL; int index = 0; while (1) { char *p = malloc(LINE_MAX); if (!p) return NULL; if (1 > fscanf(fp, "%s\n", p)) return NULL; arraySize++; char **newSeats = realloc(allSeats, sizeof(char*)*arraySize); if (!newSeats) return NULL; allSeats = newSeats; allSeats[index] = p; index++; if (feof(fp)) break; } return allSeats; } size_t lineLength = 0; int occupied(char **array, int x, int y) { int columnMax = lineLength-1; int rowMax = arraySize-1; if ((x < 0 || x > rowMax) || (y < 0 || y > columnMax)) return 0; int upRow = x - 1; if (upRow < 0) upRow = 0; int downRow = x + 1; if (downRow > rowMax) downRow = rowMax; int left = y - 1; if (left < 0) left = 0; int right = y + 1; if (right > columnMax) right = columnMax; int occupiedCount = 0; for (int i = upRow; i <= downRow; i++) { for (int j = left; j <= right; j++) { if (i == x && j == y) continue; if (array[i][j] == '#') occupiedCount++; } } return occupiedCount; } void freeAllSeats(char **array) { for (int i = 0; i < arraySize; i++) free(array[i]); free(array); } int previouslyChanged = 0; int currentlyChanged = 0; char **checkBoard(char **currentBoard, char **newBoard) { currentlyChanged = 0; for (int i = 0; i < arraySize; i++) { char temp[lineLength+1]; temp[lineLength] = 0; for (size_t j = 0; j < lineLength; j++) { char *current = ¤tBoard[i][j]; char new = *current; switch (*current) { case 'L': if (!occupied(currentBoard, i, j)) { new = '#'; currentlyChanged = 1; } break; case '#': if (occupied(currentBoard, i, j) >= 4) { new = 'L'; currentlyChanged = 1; } break; } temp[j] = new; } sprintf(newBoard[i], "%s", temp); } freeAllSeats(currentBoard); return newBoard; } int countOccupied(char **currentBoard) { int occupiedCount = 0; for (int i = 0; i < arraySize; i++) { for (size_t j = 0; j < lineLength; j++) { char *current = ¤tBoard[i][j]; if (*current == '#') { occupiedCount++; } } } return occupiedCount; } char **allocateNewBoard(int rows, int columns) { char **newBoard = malloc(sizeof(char*)*rows); if (!newBoard) return NULL; for (int i = 0; i < rows; i++) { newBoard[i] = malloc(columns); if (!newBoard[i]) return NULL; } return newBoard; } int doRounds(char **array) { char **currentBoard = array; int runs = 0; char **newBoard = NULL; while (1) { newBoard = allocateNewBoard(arraySize, lineLength+1); if (!newBoard) return -1; if (runs > 1 && ((currentlyChanged == 0) && (previouslyChanged == 0))) break; previouslyChanged = currentlyChanged; currentBoard = checkBoard(currentBoard, newBoard); runs++; } int occupied = countOccupied(currentBoard); freeAllSeats(currentBoard); freeAllSeats(newBoard); return occupied; } int occupied2(char **array, int x, int y) { int columnMax = lineLength; int rowMax = arraySize; int occupiedCount = 0; for (int i = x+1; i < rowMax; i++) { if (array[i][y] == '#') { occupiedCount++; break; } if (array[i][y] != '.') break; } for (int i = x-1; i >= 0; i--) { if (array[i][y] == '#') { occupiedCount++; break; } if (array[i][y] != '.') break; } for (int i = y+1; i < columnMax; i++) { if (array[x][i] == '#') { occupiedCount++; break; } if (array[x][i] != '.') break; } for (int i = y-1; i >= 0; i--) { if (array[x][i] == '#') { occupiedCount++; break; } if (array[x][i] != '.') break; } int currentX = x - 1; int currentY = y - 1; while ((currentX >= 0) && (currentY >= 0)) { if (array[currentX][currentY] == '#') { occupiedCount++; break; } if (array[currentX][currentY] != '.') break; currentX--; currentY--; } currentX = x + 1; currentY = y + 1; while ((currentX < rowMax) && (currentY < columnMax)) { if (array[currentX][currentY] == '#') { occupiedCount++; break; } if (array[currentX][currentY] != '.') break; currentX++; currentY++; } currentX = x - 1; currentY = y + 1; while ((currentX >= 0) && (currentY < columnMax)) { if (array[currentX][currentY] == '#') { occupiedCount++; break; } if (array[currentX][currentY] != '.') break; currentX--; currentY++; } currentX = x + 1; currentY = y - 1; while ((currentX < rowMax) && (currentY >= 0)) { if (array[currentX][currentY] == '#') { occupiedCount++; break; } if (array[currentX][currentY] != '.') break; currentX++; currentY--; } return occupiedCount; } char **checkBoard2(char **currentBoard, char **newBoard) { currentlyChanged = 0; for (int i = 0; i < arraySize; i++) { char temp[lineLength+1]; temp[lineLength] = 0; for (size_t j = 0; j < lineLength; j++) { char *current = ¤tBoard[i][j]; char new = *current; switch (*current) { case 'L': if (!occupied2(currentBoard, i, j)) { new = '#'; currentlyChanged = 1; } break; case '#': if (occupied2(currentBoard, i, j) >= 5) { new = 'L'; currentlyChanged = 1; } break; } temp[j] = new; } sprintf(newBoard[i], "%s", temp); } freeAllSeats(currentBoard); return newBoard; } int doRounds2(char **array) { char **currentBoard = array; int runs = 0; char **newBoard = NULL; while (1) { newBoard = allocateNewBoard(arraySize, lineLength+1); if (!newBoard) return -1; if (runs > 1 && ((currentlyChanged == 0) && (previouslyChanged == 0))) break; previouslyChanged = currentlyChanged; currentBoard = checkBoard2(currentBoard, newBoard); runs++; } int occupied = countOccupied(currentBoard); freeAllSeats(currentBoard); freeAllSeats(newBoard); return occupied; } char **copyBoard(char** array, int rows, int columns) { char **newBoard = malloc(sizeof(char*)*rows); if (!newBoard) return NULL; for (int i = 0; i < rows; i++) { newBoard[i] = malloc(columns); if (!newBoard[i]) return NULL; sprintf(newBoard[i], "%s", array[i]); } return newBoard; } int main(int argc, char **argv) { if (argc < 2) { puts("You need to specify path to file!"); return -1; } FILE *fp = fopen(argv[1], "r"); if (!fp) { puts("Can't open file!"); return -1; } char **currentBoard = readSeats(fp); if (!currentBoard) { puts("Can't read numbers!"); fclose(fp); return -1; } fclose(fp); lineLength = strlen(currentBoard[arraySize-1]); char **originalBoard = copyBoard(currentBoard, arraySize, lineLength+1); if (!originalBoard) return -1; printf("Part1: %d\n", doRounds(currentBoard)); printf("Part2: %d\n", doRounds2(originalBoard)); }