#include #include #include #include // How much memory to allocate for each line #define MAX_LINE_LEN 200 #define DEFAULT_FILE "input.txt" // Returns 0 if a string is not a number (e.g. 'two') // Otherwise, returns the equivilant ascii character digit. // Only works for single digits. // Only accepts lower case. char parse_num(char *str) { const char *num_strings[10] = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; // The lengths of the strings above, const uint8_t num_string_lens[10] = { 4, 3, 3, 5, 4, 4, 3, 5, 5, 4 }; bool possible_nums[10] = { [0 ... 9] = true }; uint8_t num_idx = 0; uint8_t char_incriment = 0; char current; bool result_still_possible = false; for (char_incriment = 0; char_incriment < 6; char_incriment++) { // Grab out next character in the string current = *(str + char_incriment); for (num_idx = 0; num_idx < 10; num_idx++) { if (!possible_nums[num_idx]) continue; // If we have passed the end of our number string and every character has matched, // then we return our valid character. if (char_incriment == num_string_lens[num_idx] && possible_nums[num_idx]) return (num_idx + '0'); // If the character is not the letter it should be, disqualify this number. // e.g. if num_idx == 1 and char_incriment == 2, current should equal 'e' // because 'e' is the 3rd number in the word 'one.' if (current != num_strings[num_idx][char_incriment]) possible_nums[num_idx] = false; else result_still_possible = true; } if (!result_still_possible) return 0; } return 0; } // Returns a string of the next line. // Remember to free() this after you're finished. // Limited by MAX_LINE_LEN (I'm lazy.) char *next_line(FILE *file) { char *strbuf = malloc(sizeof(char) * MAX_LINE_LEN); uint8_t idx = 0; char current = 0; while (current != '\n' && current != EOF) { current = fgetc(file); strbuf[idx] = current; idx++; } return strbuf; } int main(int argc, char **argv) { // Get filename as an argument 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; } int8_t firstdigit = -1; int8_t lastdigit = -1; int8_t parsed_num = -1; uint32_t sum = 0; char current = 0; char *strbuf = next_line(file); uint8_t strbuf_idx = 0; while (current != EOF) { parsed_num = parse_num(strbuf + strbuf_idx); current = strbuf[strbuf_idx++]; if (current == '\n') { if (lastdigit == -1) lastdigit = firstdigit; sum += (firstdigit * 10) + lastdigit; firstdigit = -1; lastdigit = -1; strbuf_idx = 0; free(strbuf); strbuf = next_line(file); continue; } if (parsed_num != 0) current = parsed_num; if (current < '0' || current > '9') continue; if (firstdigit == -1) { firstdigit = current - '0'; } else { lastdigit = current - '0'; } } printf("Sum: %d\n", sum); return 0; }