203 lines
5.3 KiB
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;
|
|
}
|