diff options
author | Thomas Voss <thomasvoss@live.com> | 2021-10-29 23:02:39 +0200 |
---|---|---|
committer | Thomas Voss <thomasvoss@live.com> | 2021-10-29 23:02:39 +0200 |
commit | e7c9108b95e39d7ea5a29ae06d619c4727f11027 (patch) | |
tree | 237261eef3afd0720be77dbcbb9599fa66a24b67 /2020/18/puzzles.c |
Initial commit
Diffstat (limited to '2020/18/puzzles.c')
-rw-r--r-- | 2020/18/puzzles.c | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/2020/18/puzzles.c b/2020/18/puzzles.c new file mode 100644 index 0000000..5afbe00 --- /dev/null +++ b/2020/18/puzzles.c @@ -0,0 +1,126 @@ +#define _GNU_SOURCE +#include <sys/types.h> + +#include <ctype.h> +#include <err.h> +#include <stdio.h> +#include <stdlib.h> + +static unsigned long long parse_number(void); +static unsigned long long parse_digit(void); +static unsigned long long parse_result(void); + +#ifdef PART2 +static unsigned long long parse_sum(void); +static unsigned long long parse_product(void); +#endif + +char *g_current; + +/* Convert the current number from a string to an int */ +unsigned long long +parse_number(void) +{ + unsigned long long number = 0; + while (isdigit(*g_current)) + number = number * 10 + *g_current++ - '0'; + + return number; +} + +/* Parse the current digit pointed to by `g_current` */ +unsigned long long +parse_digit(void) +{ + if (isdigit(*g_current)) + return parse_number(); + + /* If not a digit, it's a parenthesis */ + g_current++; + unsigned long long result = parse_result(); + g_current++; + return result; +} + +#ifdef PART2 +/* Parse and compute a sum */ +unsigned long long +parse_sum(void) +{ + unsigned long long result = parse_digit(); + + while (*g_current == '+') { + g_current++; + result += parse_digit(); + } + + return result; +} + +/* Parse and compute a product */ +unsigned long long +parse_product(void) +{ + unsigned long long result = parse_sum(); + + while (*g_current == '*') { + g_current++; + result *= parse_sum(); + } + + return result; +} +#endif + +/* Parse and compute a sum */ +unsigned long long +parse_result(void) +{ +#ifdef PART2 + return parse_product(); +#else + unsigned long long result = parse_digit(); + + while (*g_current == '+' || *g_current == '*') { + if (*g_current++ == '+') + result += parse_digit(); + else + result *= parse_digit(); + } + + return result; +#endif +} + +/* Remove the spaces from user input */ +static void +remove_spaces(char *str) +{ + char const *c = str; + do + while (*c == ' ') + c++; + while ((*str++ = *c++)); +} + +int +main(void) +{ + FILE *fp; + char *line = NULL; + size_t len = 0; + ssize_t read; + + if (!(fp = fopen("input", "r"))) + err(EXIT_FAILURE, "fopen"); + + unsigned long long acc = 0; + while ((read = getline(&line, &len, fp)) != -1) { + remove_spaces(line); + g_current = line; + acc += parse_result(); + } + + printf("%llu\n", acc); + return EXIT_SUCCESS; +} |