Files
adventofcode2023/day3/c/day3.c
dobiadi 7913dcea4a Day3 C
2023-12-03 11:41:50 +01:00

156 lines
4.1 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LINE_MAX_LENGTH 256
#define MAX_MAP_SIZE 1024
#define MAX_NUMBERS 32*1024
#define abs(a) ((a) < 0 ? -(a) : (a))
struct num_position_t {
int x;
int y;
int length;
unsigned int value;
};
struct num_position_t* create_position(int x, int y, int length, unsigned int value);
int has_adjacent_symbol(struct num_position_t* number, int symbol_map[MAX_MAP_SIZE][MAX_MAP_SIZE]);
unsigned int gear_ratio(int x, int y, struct num_position_t** numbers, int num_numbers);
int main() {
char *p, *buf, c, tmp[64];
struct num_position_t **numbers, *tmp_pos;
numbers = (struct num_position_t**)malloc(MAX_NUMBERS * sizeof(struct num_position_t*));
int symbol_map[MAX_MAP_SIZE][MAX_MAP_SIZE];
memset(symbol_map, 0, MAX_MAP_SIZE*MAX_MAP_SIZE*sizeof(int));
int num_numbers = 0, num_length = 0;
unsigned int curr = 0;
int x = 0, y = 0;
buf = (char *)malloc(LINE_MAX_LENGTH);
memset(buf, 0, LINE_MAX_LENGTH);
p = buf;
int map_x = 0;
int map_y = 0;
while ((c = getchar()) != EOF) {
*p++ = c;
if (c == '\n') {
p = buf;
while (*p != '\n') {
if (*p == '-' || *p == '+') {
symbol_map[x][y] = 1;
p++;
x++;
} else if (sscanf(p, "%u", &curr) != 0) {
num_length = sprintf(tmp, "%u", curr);
tmp_pos = create_position(x, y, num_length, curr);
numbers[num_numbers] = tmp_pos;
num_numbers++;
p += num_length;
x += num_length;
} else {
if (*p != '.') {
symbol_map[x][y] = 1;
}
if (*p == '*') {
symbol_map[x][y] = 2;
}
p++;
x++;
}
}
map_x = x;
x = 0;
y++;
memset(buf, 0, LINE_MAX_LENGTH);
p = buf;
}
}
map_y = y;
// Part 1
unsigned int part1 = 0;
for (int i = 0; i < num_numbers; i++) {
if (has_adjacent_symbol(numbers[i], symbol_map)) {
part1 += numbers[i]->value;
}
}
printf("%u\n", part1);
// Part 2
unsigned int part2 = 0;
for (int i = 0; i < map_y; i++) {
for (int j = 0; j < map_x; j++) {
if (symbol_map[j][i] == 2) {
part2 += gear_ratio(j, i, numbers, num_numbers);
}
}
}
printf("%u\n", part2);
free(buf);
for (int i = 0; i < num_numbers; i++) {
free(numbers[i]);
}
free(numbers);
}
struct num_position_t* create_position(int x, int y, int length, unsigned int value) {
struct num_position_t *pos;
pos = (struct num_position_t*)malloc(sizeof(struct num_position_t));
pos->x = x;
pos->y = y;
pos->length = length;
pos->value = value;
return pos;
}
int has_adjacent_symbol(struct num_position_t* number, int symbol_map[MAX_MAP_SIZE][MAX_MAP_SIZE]) {
int x, y;
for (int i = 0; i < number->length; i++) {
for (int j = -1; j <= 1; j++) {
for (int k = -1; k <= 1; k++) {
x = number->x + i + j;
y = number->y + k;
if (x < 0 || y < 0) continue;
if (symbol_map[x][y]) return 1;
}
}
}
return 0;
}
unsigned int gear_ratio(int x, int y, struct num_position_t** numbers, int num_numbers) {
int gear_num = 0;
unsigned int num_parts[2];
for (int i = 0; i < num_numbers; i++) {
for (int j = 0; j < numbers[i]->length; j++) {
if (abs(numbers[i]->x + j - x) <= 1 && abs(numbers[i]->y - y) <= 1) {
// Not a gear
if (gear_num == 2) return 0;
// Add gear
num_parts[gear_num] = numbers[i]->value;
gear_num++;
break;
}
}
}
if (gear_num == 2) {
return num_parts[0] * num_parts[1];
}
return 0;
}