147 lines
4.0 KiB
C
147 lines
4.0 KiB
C
//
|
|
// Created by lennart on 12/6/23.
|
|
//
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
#include <ctype.h>
|
|
#include "input_handler.h"
|
|
|
|
typedef struct {
|
|
char **data;
|
|
int height;
|
|
int width;
|
|
} PartsMap;
|
|
|
|
// Functions
|
|
PartsMap* load_map(const char *file_name);
|
|
void free_map(PartsMap *map);
|
|
bool is_adjacent_to_symbol(PartsMap *map, int row, int col, int len);
|
|
bool is_gear(PartsMap *map, int g_row, int g_col, int *num1, int *num2);
|
|
|
|
int main() {
|
|
PartsMap *map = load_map("day_3.txt");
|
|
|
|
// Part 1 - Iterate over each row and find numbers with adjacent symbols
|
|
int sum = 0;
|
|
for(int row = 0; row < map->height; row++) {
|
|
const char *begin = &map->data[row][0];
|
|
char *pos = (char*) begin;
|
|
while(*pos != 0) {
|
|
const char *before = pos;
|
|
if(isdigit(*pos)) {
|
|
unsigned long num = strtoul(before, &pos, 10);
|
|
if(is_adjacent_to_symbol(map, row, (int) (before - begin), (int) (pos - before))) {
|
|
sum += (int) num;
|
|
}
|
|
} else {
|
|
pos++;
|
|
}
|
|
}
|
|
}
|
|
printf("Result #1: %i\n", sum);
|
|
|
|
// Part 2 - Iterate over each row and find gear symbols (*) with 2 adjacent numbers
|
|
sum = 0;
|
|
for(int row = 0; row < map->height; row++) {
|
|
for(int col = 0; col < map->width; col++) {
|
|
if(map->data[row][col] == '*') {
|
|
int num1, num2;
|
|
if(is_gear(map, row, col, &num1, &num2)) {
|
|
sum += num1 * num2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
printf("Result #2: %i", sum);
|
|
|
|
free_map(map);
|
|
}
|
|
|
|
bool is_gear(PartsMap *map, int g_row, int g_col, int *num1, int *num2) {
|
|
int count = 0;
|
|
|
|
int rowMin = max(g_row - 1, 0);
|
|
int rowMax = min(g_row + 1, map->height - 1);
|
|
int colMin = max(g_col - 1, 0);
|
|
int colMax = min(g_col + 1, map->width - 1);
|
|
|
|
for(int row = rowMin; row <= rowMax; row++) {
|
|
const char *begin = &map->data[row][0];
|
|
char *pos = &map->data[row][colMin];
|
|
while(isdigit(*pos) && pos > begin) {
|
|
pos--;
|
|
}
|
|
while(pos - begin <= colMax) {
|
|
if(isdigit(*pos)) {
|
|
const char *before = pos;
|
|
unsigned long num = strtoul(before, &pos, 10);
|
|
if(++count == 1) {
|
|
*num1 = (int) num;
|
|
} else if(count == 2) {
|
|
*num2 = (int) num;
|
|
} else {
|
|
return false; // More than 2 adjacent numbers
|
|
}
|
|
} else {
|
|
pos++;
|
|
}
|
|
}
|
|
}
|
|
return count == 2;
|
|
}
|
|
|
|
bool is_adjacent_to_symbol(PartsMap *map, int row, int col, int len) {
|
|
int rowMin = max(row - 1, 0);
|
|
int rowMax = min(row + 2, map->height);
|
|
int colMin = max(col - 1, 0);
|
|
int colMax = min(col + len + 1, map->width);
|
|
for(int cr = rowMin; cr < rowMax; cr++) {
|
|
for(int cc = colMin; cc < colMax; cc++) {
|
|
char c = map->data[cr][cc];
|
|
if(c != '.' && !isdigit(c)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
PartsMap* load_map(const char *file_name) {
|
|
FILE *f = fopen(file_name, "r");
|
|
if(f == NULL) {
|
|
printf("ERROR: Input file not found!");
|
|
exit(1);
|
|
}
|
|
|
|
char *buffer = NULL;
|
|
int bufferLen = 0;
|
|
|
|
size_t length = 16;
|
|
PartsMap *map = malloc(sizeof (PartsMap));
|
|
map->height = 0;
|
|
map->data = malloc(sizeof (map->data) * length);
|
|
while(!feof(f)) {
|
|
if(map->height >= length) {
|
|
map->data = realloc(map->data, sizeof (map->data) * (length *= 2));
|
|
}
|
|
read_line(f, &buffer, &bufferLen);
|
|
map->data[map->height++] = strdup(buffer);
|
|
}
|
|
map->width = strlen(map->data[0]);
|
|
|
|
fclose(f);
|
|
free(buffer);
|
|
return map;
|
|
}
|
|
|
|
void free_map(PartsMap *map) {
|
|
for(size_t row = 0; row < map->height; row++) {
|
|
free(map->data[row]);
|
|
}
|
|
free(map->data);
|
|
free(map);
|
|
}
|