#include #include #include #include #include #include int rows = 0; int columns; typedef struct { int pos[2]; int sum; int len; } number; typedef struct { int length; int listSize; long unsigned int gearSum; number numbers[]; } numberList; numberList *findNumbers(); numberList *addNumber(numberList *list, int sum, int len, int col, int row); int readNumber(char **schematic, int *len, int *col, int row); unsigned long int checkNumbers(char **schematic, numberList *list, int rows, int columns); int main () { int columnsc = 0; char c; numberList *list = malloc(sizeof(int) * 2 + sizeof(long unsigned int) + sizeof(number) * 8); list->listSize = 8; list->length = 0; FILE *input; input = fopen("./input", "r"); // see dimensions of file while ((c = fgetc(input)) != EOF) { if (c == '\n') { rows++; if (columns < columnsc) columns = columnsc; columnsc = 0; } else { // I could probably not do this every row but w/e columnsc++; } } // allocate memory for the char array array char **schematic = malloc(columns * sizeof(char*)); for (int i = 0; i < columns; i++) schematic[i] = malloc(rows * sizeof(char*)); // read the file again to fill up the array rewind(input); for (int row = 0; row < rows; row++) { for (int col = 0; col < columns; col++) { schematic[col][row] = fgetc(input); } fgetc(input); // discard \n } fclose(input); // just print the damn thing // for (int row = 0; row < rows; row++) { // for (int col = 0; col < columns; col++) { // printf("%c", schematic[col][row]); // } // printf("\n"); // } printf("\nRows: %d\nColumns: %d\n\n", rows, columns); list = findNumbers(schematic, list); printf("Found %d numbers.\n", list->length); printf("Total sum is %lu.\n", checkNumbers(schematic, list, rows, columns)); printf("Gear ratio sum is %lu.\n", list->gearSum); } // Test gear: count how many numbers are around it, if 2, multiply and return product int checkGear(char **schematic, int col, int row) { int numbers[2]; int foundNumbers = 0; int ratio = 0; for (int y = row - 1; y <= row + 1; y++) { if (y < 0) y++; for (int x = col + 1; x >= col - 1; x--) { if (x >= columns) x--; if (x < 0) break; while (x < columns - 1 &&(schematic[x][y] >= '0' && schematic[x][y] <= '9' && schematic[x + 1][y] >= '0' && schematic[x + 1][y] <= '9')) { x++; } if (schematic[x][y] >= '0' && schematic[x][y] <= '9') { if (foundNumbers >= 2) { foundNumbers++; } int len = 0; // TODO: Really not needed numbers[foundNumbers] = readNumber(schematic, &len, &x, y); foundNumbers++; } } } if (foundNumbers == 2) { ratio = numbers[0] * numbers[1]; printf("Values: %d and %d = %d\n", numbers[0], numbers[1], numbers[0] * numbers[1]); } return ratio; } // Why is len a ptr? because I need to return two values duh int readNumber(char **schematic, int *len, int *col, int row) { int sum = 0; while (*col >= 0 && schematic[*col][row] >= '0' && schematic[*col][row] <= '9') { sum += (schematic[*col][row] - '0') * (int)pow(10, *len); (*len)++; (*col)--; } (*col)++; return sum; } // for each number in list, check adjacent fields unsigned long int checkNumbers(char **schematic, numberList *list, int rows, int columns) { unsigned long int sum = 0; int previous; for(int i = 0; i < list->length; i++) { // make sure col or row is never too high / low number num = list->numbers[i]; for (int row = num.pos[1] - 1; row <= num.pos[1] + 1; row++) { if (row < 0) row++; if (row >= rows) break; for (int col = num.pos[0] - 1; col < num.pos[0] + num.len + 1; col++) { if (col < 0) col++; if (col >= columns) break; char c = schematic[col][row]; if (!isdigit(c) && c != '.'){ previous = num.sum; sum += num.sum; goto nextIteration; } } } nextIteration: } return sum; } // för varje position i 2D-arrayen, om siffra, leta efter dess "start" genom att gå åt vänster // lagra en "pekare" till starten, längden (antalet siffror) och totalvärdet // ^ gör en lista av dessa // hoppa till slutet av den man hittade och iterera vidare genom sökfältet numberList *findNumbers(char **schematic, numberList *list) { for (int row = 0; row < rows; row++) { for (int col = columns - 1; col >= 0; col--) { if (schematic[col][row] == '*') { int sum = checkGear(schematic, col, row); printf("%d + %d = ", list->gearSum, sum); list->gearSum += sum; printf("%d\n", list->gearSum); } if (schematic[col][row] >= '0' && schematic[col][row] <= '9') { int len = 0; int sum = readNumber(schematic, &len, &col, row); list = addNumber(list, sum, len, col, row); } } } return list; } numberList *addNumber(numberList *list, int sum, int len, int col, int row) { if (list->length >= list->listSize) { list->listSize = list->listSize * 2; printf("Resizing!\n", list->listSize, list->length); printf("size: %d length: %d\n", list->listSize, list->length); list = realloc(list, list->listSize * sizeof(number) + sizeof(int) * 2 + sizeof(long unsigned int)); } list->numbers[list->length].pos[0] = col + 1; list->numbers[list->length].pos[1] = row; list->numbers[list->length].sum = sum; list->numbers[list->length].len = len; list->length++; return list; }