106 lines
2.5 KiB
C
106 lines
2.5 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
|
|
#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;
|
|
}
|