#include #include #include #include #include #define STRBUF_SIZE 200 #define DEFAULT_FILE "input.txt" #define ISDIGIT(X) (X >= '0' && X <= '9') // Parses a found number. // The provided location can be any digit of the // number; this function will automatically // seek the first digit before processing. // Erases numbers as they are processed. uint16_t parse_num_at(char *str, uint8_t idx) { // Check input if (str[idx] < '0' || str[idx] > '9') return 0; // Find first digit of number while (ISDIGIT(str[idx]) && idx) idx--; if (!ISDIGIT(str[idx])) idx++; uint16_t num = 0; // Add up all digits while (ISDIGIT(str[idx])) { num = (num * 10) + (str[idx] - '0'); // Erase the number to make sure we don't count it twice str[idx] = '.'; idx++; } return num; } // Returns the sum of all numbers around a symbol, // including diagonals. uint16_t search_numbers_around( uint8_t idx, char *above, char *current, char *below) { uint16_t sum = 0; if (idx) sum += parse_num_at(above, idx - 1); sum += parse_num_at(above, idx); sum += parse_num_at(above, idx + 1); sum += parse_num_at(current, idx + 1); sum += parse_num_at(current, idx - 1); if (idx) sum += parse_num_at(below, idx - 1); sum += parse_num_at(below, idx); sum += parse_num_at(below, idx + 1); return sum; } // Search through a line of *current for symbols. // returns the sum for that line (erases numbers as // they are processed.) uint16_t parse_line(char *above, char *current, char *below) { uint16_t sum = 0; uint8_t idx; char c; for (idx = 0; current[idx] != 0; idx++) { c = current[idx]; if (!ISDIGIT(c) && c != '.' && c != '\n') { // We've found a symbol, // add up all numbers around it sum += search_numbers_around(idx, above, current, below); } } return sum; } int main(int argc, char **argv) { // Get filename as an argument, defaults to "input.txt" char *path = (argc > 1) ? argv[1] : DEFAULT_FILE; if (!path) { printf("Requires input file.\n"); return 1; } FILE *file = fopen(path, "r"); if (!file) { printf("Could not find file."); return 1; } char *above = malloc(sizeof(char) * STRBUF_SIZE); char *current = malloc(sizeof(char) * STRBUF_SIZE); char *below = malloc(sizeof(char) * STRBUF_SIZE); memset(above, '.', STRBUF_SIZE); fgets(current, STRBUF_SIZE, file); uint32_t sum = 0; while (fgets(below, 200, file)) { sum += parse_line(above, current, below); free(above); above = current; current = below; below = malloc(sizeof(char) * STRBUF_SIZE); memset(below, '.', STRBUF_SIZE); } // Process the last line of the file sum += parse_line(above, current, below); printf("Sum: %d\n", sum); return 0; }