aboutsummaryrefslogtreecommitdiff
path: root/advent-of-code/2023/03/part1.c
blob: 4ae9ef9ded491d6f11d2fab965474cf68474fd5e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>

#include "vec.h"
#include "str.h"

void* read_input() {
    FILE* fp = fopen("./input", "r");
    void *vec = new_vec();
    while(1) {
        char *line = fgetline(fp);
        if (line == NULL) break;
        char *stripped = str_strip(line);
        if (strlen(stripped) == 0) break;
        vec_push_back(vec, stripped);
    }
    return vec;
}

typedef struct {
    int line;
    int column;
    int value;
    int length;
} num_t;

void *parse_nums(void *schema) {
    void *nums = new_vec();
    int j = 0;
    const int IN_NUM = 0, IDLE = 1;
    int state = IDLE;
    for (int i = 0; i < vec_size(schema); i++) {
        char *line = vec_get(schema, i);
        int line_len = strlen(line);
        int value = 0;
        int length = 0;
        state = IDLE;
        j = 0;
        while (1) {
            char c = '.';
            if (j < line_len) c = line[j];
            if (state == IDLE) {
                if (isdigit(c)) {
                    state = IN_NUM;
                    continue;
                } else {
                    j++;
                    if (j >= line_len) break;
                    continue;
                }
            } else if (state == IN_NUM) {
                if (isdigit(c)) {
                    value = value * 10 + (c - '0'); 
                    length++;
                    j++;
                    continue;
                } else {
                    num_t *n = malloc(sizeof(num_t));
                    *n = (num_t){
                        .line = i,
                        .column = j - length,
                        .value = value,
                        .length = length
                    };
                    vec_push_back(nums, n);
                    value = 0;
                    length = 0;
                    state = IDLE;
                    if (j >= line_len) break;
                    continue;
                }
            }
        }
    }
    return nums;
}

int is_symbol(char c) {
    if (c >= '0' && c <= '9') return 0;
    if (c == '.') return 0;
    return 1;
}

int is_a_part(void *schema, num_t *num) {    
    int line_len = vec_size(schema);
    int col_len = strlen(vec_get(schema, 0));
    for (int i = num->column - 1; i < num->column + num->length + 1; i++) {
        if (num->line - 1 < 0) continue;
        if (i < 0 || i >= col_len) continue;
        if (is_symbol(((char*)vec_get(schema, num->line - 1))[i])) {
            return 1;
        }
    }
    for (int i = num->column - 1; i < num->column + num->length + 1; i++) {
        if (num->line + 1 >= line_len) continue;
        if (i < 0 || i >= col_len) continue;
        if (is_symbol(((char*)vec_get(schema, num->line + 1))[i])) {
            return 1;
        }
    }
    if (num->column - 1 >= 0) {
        if (is_symbol(((char*)vec_get(schema, num->line))[num->column - 1])) {
            return 1;
        }
    }
    if (num->column + num->length < col_len) {
        char *line = vec_get(schema, num->line);
        if (is_symbol(line[num->column + num->length])) {
            return 1;
        }
    }
    return 0;
}

int main() {
    void *schema = read_input();
    void *nums = parse_nums(schema);
    int sum = 0;
    for (int i = 0; i < vec_size(nums); i++) {
        num_t *num = vec_get(nums, i);
        if (is_a_part(schema, num)) {
            sum += num->value;
        }
    }
    printf("%d\n", sum);
    return 0;
}