156 lines
4.1 KiB
C
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;
|
|
}
|