2024-12-07 01:26:23 -06:00

122 lines
2.7 KiB
C

#include <stdint.h>
#include <stdbool.h>
#include "parse.h"
#include "printf.h"
#include "unparse.h"
struct equation {
int64_t value;
int operand[32];
int operand_count;
};
const char * parse_equation(const char * input, const char * end, struct equation * equation)
{
input = parse_base10_64(input, &equation->value);
input = parse_skip(input, ':');
input = parse_skip(input, ' ');
equation->operand_count = 0;
while (*input != '\n') {
input = parse_base10(input, &equation->operand[equation->operand_count++]);
input = parse_skip(input, ' ');
}
return parse_skip(input, '\n');
}
static bool evaluate_equation1(struct equation * equation, int64_t acc, int depth)
{
if (depth >= equation->operand_count)
return acc == equation->value;
int64_t operand = equation->operand[depth];
int64_t acc1 = acc * operand;
int64_t acc2 = acc + operand;
return
evaluate_equation1(equation, acc1, depth + 1)
|| evaluate_equation1(equation, acc2, depth + 1);
}
int64_t day7_part1(const char * input, int length)
{
const char * end = input + length;
int64_t sum = 0;
while (input < end) {
struct equation equation;
input = parse_equation(input, end, &equation);
bool possible = evaluate_equation1(&equation, equation.operand[0], 1);
if (possible)
sum += equation.value;
}
return sum;
}
static int64_t pow10[20] = {
1ull,
10ull,
100ull,
1000ull,
10000ull,
100000ull,
1000000ull,
10000000ull,
100000000ull,
1000000000ull,
10000000000ull,
100000000000ull,
1000000000000ull,
10000000000000ull,
100000000000000ull,
1000000000000000ull,
10000000000000000ull,
100000000000000000ull,
1000000000000000000ull,
10000000000000000000ull,
};
int64_t concatenate(int64_t a, int64_t b)
{
int digits = digits_base10_64(b);
a *= pow10[digits];
return a + b;
}
static bool evaluate_equation2(struct equation * equation, int64_t acc, int depth)
{
if (depth >= equation->operand_count)
return acc == equation->value;
int64_t operand = equation->operand[depth];
int64_t acc1 = acc * operand;
int64_t acc2 = acc + operand;
int64_t acc3 = concatenate(acc, operand);
return
evaluate_equation2(equation, acc1, depth + 1)
|| evaluate_equation2(equation, acc2, depth + 1)
|| evaluate_equation2(equation, acc3, depth + 1);
}
int64_t day7_part2(const char * input, int length)
{
const char * end = input + length;
int64_t sum = 0;
while (input < end) {
struct equation equation;
input = parse_equation(input, end, &equation);
bool possible = evaluate_equation2(&equation, equation.operand[0], 1);
if (possible)
sum += equation.value;
}
return sum;
}