diff options
author | Anna (navi) Figueiredo Gomes <navi@vlhl.dev> | 2023-12-02 03:15:25 +0100 |
---|---|---|
committer | Anna (navi) Figueiredo Gomes <navi@vlhl.dev> | 2023-12-02 04:16:37 +0100 |
commit | ed5c11ee2fd03bd351d6cd0ef41484ca7aefbfca (patch) | |
tree | c3bb8bafe0436c258b9b2fbee9af0c8501694f10 /trebuchet |
Diffstat (limited to 'trebuchet')
-rw-r--r-- | trebuchet/trebuchet.c | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/trebuchet/trebuchet.c b/trebuchet/trebuchet.c new file mode 100644 index 0000000..72e735e --- /dev/null +++ b/trebuchet/trebuchet.c @@ -0,0 +1,117 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +static int first_half(FILE *fp) { + size_t total = 0, size; + ssize_t len; + ssize_t first, last; + char *line = NULL; + while ((len = getline(&line, &size, fp)) != -1) { + line[--len] = '\0'; + first = last = -1; + for (size_t i = 0; i <= len; i++) { + if (first == -1 && isdigit(line[i])) { + first = line[i] - '0'; + } + + if (last == -1 && isdigit(line[len - i])) { + last = line[len - i] - '0'; + } + + if (first > -1 && last > -1) + break; + } + + if (first == -1 || last == -1) { + fprintf(stderr, "failed to find digit in input string: %s\n", line); + free(line); + return EXIT_FAILURE; + } + total += (first * 10) + last; + } + + free(line); + printf("result: %ld\n", total); + return EXIT_SUCCESS; +} + +const struct { + size_t num; + char *text; +} table[] = { + { 1, "one" }, + { 2, "two" }, + { 3, "three" }, + { 4, "four" }, + { 5, "five" }, + { 6, "six" }, + { 7, "seven" }, + { 8, "eight" }, + { 9, "nine" }, +}; + +inline static ssize_t lookup_num(char *line, size_t i) { + if (isdigit(line[i])) + return line[i] - '0'; + + for (size_t t = 0; t < sizeof(table) / sizeof(*table); t++) + if (strncmp(&line[i], table[t].text, strlen(table[t].text)) == 0) + return table[t].num; + + return -1; +} + +static int second_half(FILE *fp) { + size_t total = 0, size; + ssize_t len; + ssize_t first, last; + char *line = NULL; + while ((len = getline(&line, &size, fp)) != -1) { + line[--len] = '\0'; + first = last = -1; + for (size_t i = 0; i <= len; i++) { + if (first == -1) + first = lookup_num(line, i); + if (last == -1) + last = lookup_num(line, len - i); + + if (first > -1 && last > -1) + break; + } + + if (first == -1 || last == -1) { + fprintf(stderr, "failed to find digit in input string: %s\n", line); + free(line); + return EXIT_FAILURE; + } + total += (first * 10) + last; + } + + free(line); + printf("result: %ld\n", total); + return EXIT_SUCCESS; +} + +int main(int argc, char **argv) { + if (argc != 2) { + fprintf(stderr, "usage: %s <input>\n", argv[0]); + return EXIT_FAILURE; + } + + FILE *fp = fopen(argv[1], "r"); + if (!fp) { + fprintf(stderr, "failed to open input file: %s\n", argv[1]); + return EXIT_FAILURE; + } + + const char *half; + int ret; + if ((half = getenv("AOC_TREBUCHET_HALF")) && strcmp(half, "first") == 0) + ret = first_half(fp); + else + ret = second_half(fp); + fclose(fp); + return ret; +} |