Files
adventofcode2024/day13/c/day13.c
dobiadi 5773eee507 Day13
2024-12-14 03:12:16 +01:00

150 lines
4.1 KiB
C

#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <omp.h>
#define CHARS_MAX 64
#define MAX_MACHINES 1024
#define max(a,b) ((a) > (b) ? (a) : (b))
#define min(a,b) ((a) < (b) ? (a) : (b))
typedef struct button {
uint64_t x;
uint64_t y;
} button_t;
typedef struct machine {
button_t button_A;
button_t button_B;
uint64_t x;
uint64_t y;
} machine_t;
int64_t extended_euclidian(int64_t a, int64_t b, int64_t *x, int64_t *y);
int main() {
char *p, *buf, c;
buf = calloc(CHARS_MAX, sizeof(char));
p = buf;
int step = 0;
machine_t *machines = calloc(MAX_MACHINES, sizeof(machines[0]));
int machine_count = 0;
while ((c = getchar()) != EOF) {
*p++ = c;
if (c != '\n') {
continue;
}
switch (step) {
case 0:
p = buf;
while (*p != '+') p++;
p++;
sscanf(p, "%lu", &machines[machine_count].button_A.x);
while (*p != '+') p++;
p++;
sscanf(p, "%lu", &machines[machine_count].button_A.y);
break;
case 1:
p = buf;
while (*p != '+') p++;
p++;
sscanf(p, "%lu", &machines[machine_count].button_B.x);
while (*p != '+') p++;
p++;
sscanf(p, "%lu", &machines[machine_count].button_B.y);
break;
case 2:
p = buf;
while (*p != '=') p++;
p++;
sscanf(p, "%lu", &machines[machine_count].x);
while (*p != '=') p++;
p++;
sscanf(p, "%lu", &machines[machine_count].y);
machine_count++;
break;
case 3:
break;
}
step++;
if (step == 4) {
step = 0;
}
memset(buf, 0, CHARS_MAX);
p = buf;
}
free(buf);
uint64_t tokens = 0;
#pragma omp parallel for
for (int i = 0; i < machine_count; i++) {
uint64_t least_tokens = 0;
for (int j = 0; j <= 100; j++) {
for (int k = 0; k <= 100; k++) {
int x = machines[i].button_A.x * j + machines[i].button_B.x * k;
int y = machines[i].button_A.y * j + machines[i].button_B.y * k;
if (x == machines[i].x && y == machines[i].y) {
uint64_t current_tokens = 3 * j + k;
if (least_tokens == 0 || least_tokens > current_tokens) {
least_tokens = current_tokens;
}
}
}
}
#pragma omp critical
{
tokens += least_tokens;
}
}
printf("%lu\n", tokens);
double ttokens = 0.0;
for (int i = 0; i < machine_count; i++) {
machines[i].x += 10000000000000;
machines[i].y += 10000000000000;
//printf("%i %lu %lu %lu %lu %lu %lu\n", i, machines[i].x, machines[i].y, machines[i].button_A.x, machines[i].button_A.y, machines[i].button_B.x, machines[i].button_B.y);
int64_t x, y;
double a = (double)machines[i].button_A.x - (double)machines[i].button_A.y;
double b = (int64_t)machines[i].button_B.x - (double)machines[i].button_B.y;
double c = (double)machines[i].x - (double)machines[i].y;
double k2 = ((double)machines[i].x - (double)machines[i].button_A.x * c / a) / ((double)machines[i].button_B.x - (double)machines[i].button_A.x * b / a);
double k1 = (c - b * k2) / a;
double tmp;
double r1 = modf(k1, &tmp);
double r2 = modf(k2, &tmp);
if ((r1 < 0.001 || r1 > 0.999) && (r2 < 0.001 || r2 > 0.999)) {
ttokens += k1 * 3.0 + k2;
}
}
printf("%0.0f\n", ttokens);
free(machines);
}
int64_t extended_euclidian(int64_t a, int64_t b, int64_t *x, int64_t *y) {
if (a == 0) {
*x = 0;
*y = 1;
return b;
}
int64_t x1, y1;
int64_t gcd = extended_euclidian(b % a, a, &x1, &y1);
*x = y1 - (b / a) * x1;
*y = x1;
return gcd;
}