#include #include #include #include #include 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, ¶ms[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); }