AoC2023/day3/day3a.c

203 lines
5.3 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <math.h>
#include <ctype.h>
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;
}