#include #include #include #include #include "../../lib/aoc.h" typedef struct Calibration { long test_value; int numbers[20]; int number_count; } Calibration; void base_three(char *string, int number, int length) { int i = 0; for (; i < length; i++) { string[length - i - 1] = (number % 3) + '0'; number /= 3; } string[length] = '\0'; } bool true_permutation(Calibration *c, int permutation) { long value = c->numbers[0]; for (int i = 1; i < c->number_count; i++) { int operator = permutation & 1; permutation >>= 1; if (operator == 0) { value += c->numbers[i]; } else { value *= c->numbers[i]; } } return value == c->test_value; } bool true_permutation_p2(Calibration *c, char *permutation) { long value = c->numbers[0]; for (int i = 1; i < c->number_count; i++) { int operator = permutation[i - 1]; if (operator == '0') { value += c->numbers[i]; } else if (operator == '1') { value *= c->numbers[i]; } else { char concat[100]; sprintf(concat, "%ld%d", value, c->numbers[i]); value = atol(concat); } } return value == c->test_value; } bool true_calibration(Calibration *c) { int permutation_count = 2 << (c->number_count - 2); for (int i = 0; i < permutation_count; i++) { if (true_permutation(c, i)) return true; } return false; } bool true_calibration_p2(Calibration *c) { int permutation_count = 1; for (int i = 1; i < c->number_count; i++) { permutation_count *= 3; } char permutation_string[c->number_count]; for (int i = 0; i < permutation_count; i++) { base_three(permutation_string, i, c->number_count - 1); if (true_permutation_p2(c, permutation_string)) return true; } return false; } void calibration_from_line(Calibration *c, char *line) { c->number_count = 0; char *token = strtok(line, ":"); c->test_value = atol(token); while((token = strtok(NULL, " "))) { c->numbers[c->number_count++] = atoi(token); } } int main() { char *line; Calibration c; long long calibration_result = 0; long long calibration_result_p2 = 0; while((line = aoc_read_line()) != NULL) { calibration_from_line(&c, line); if (true_calibration(&c)) { calibration_result += c.test_value; } if (true_calibration_p2(&c)) { calibration_result_p2 += c.test_value; } } printf("Part 1: %lld\n", calibration_result); printf("Part 2: %lld\n", calibration_result_p2); aoc_free(); return 0; }