Advent of Code 2019 - Lua
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
2.8 KiB

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <err.h>
#include <openssl/bn.h>
struct thread_params {
char *begin;
char *end;
BIGNUM *results[2];
};
void *thread(void *arg)
{
struct thread_params *params = arg;
char *line = params->begin;
BIGNUM *cur = NULL;
while (line && line < params->end && *line) {
BN_dec2bn(&cur, line);
BN_div_word(cur, 3);
BN_sub_word(cur, 2);
BN_add(params->results[0], params->results[0], cur);
while (!BN_is_negative(cur) && !BN_is_zero(cur)) {
BN_add(params->results[1], params->results[1], cur);
BN_div_word(cur, 3);
BN_sub_word(cur, 2);
}
line = strchr(line, '\n');
if (line) line++;
}
BN_free(cur);
return NULL;
}
int main(int argc, char *argv[])
{
long jobs = 8;
if (argc <= 1) return EXIT_FAILURE;
if (argc > 2) jobs = strtol(argv[2], NULL, 0);
FILE *f = fopen(argv[1], "r");
if (!f) err(EXIT_FAILURE, "fopen");
fseek(f, 0, SEEK_END);
long f_len = ftell(f);
fseek(f, 0, SEEK_SET);
char *file = malloc(f_len + 1);
if (!file) err(EXIT_FAILURE, "malloc");
if (fread(file, f_len, 1, f) != 1) err(EXIT_FAILURE, "fread");
file[f_len] = '\0';
fclose(f);
unsigned lines = 0;
for (char *c = file; *c; c++) if (*c == '\n') lines++;
if (file[f_len - 1] != '\n') lines++;
unsigned lines_per_job = lines / jobs;
struct thread_params params[jobs];
pthread_t threads[jobs];
char *begin = file;
char *end = begin;
for (unsigned i = 0; i < jobs; i++) {
params[i].results[0] = BN_new();
params[i].results[1] = BN_new();
if (i == jobs - 1) {
end = file + strlen(file);
} else {
for (unsigned i = 0; i < lines_per_job; i++) {
end = strchr(end, '\n');
if (!end) {
end = file + strlen(file);
break;
}
end++;
}
}
params[i].begin = begin;
params[i].end = end;
begin = end;
pthread_create(&threads[i], NULL, thread, &params[i]);
}
BIGNUM *result_p1 = BN_new();
BIGNUM *result_p2 = BN_new();
for (unsigned i = 0; i < jobs; i++) {
pthread_join(threads[i], NULL);
BN_add(result_p1, result_p1, params[i].results[0]);
BN_add(result_p2, result_p2, params[i].results[1]);
BN_free(params[i].results[0]);
BN_free(params[i].results[1]);
}
char *result_p1_str = BN_bn2dec(result_p1);
char *result_p2_str = BN_bn2dec(result_p2);
BN_free(result_p1);
BN_free(result_p2);
printf("Part 1: %s\n", result_p1_str);
printf("Part 2: %s\n", result_p2_str);
OPENSSL_free(result_p1_str);
OPENSSL_free(result_p2_str);
free(file);
}