AoC2023/day5/optDay5b.c

198 lines
5.4 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <math.h>
#include <ctype.h>
#include <pthread.h>
#define SEEDS 20
typedef struct {
unsigned long int len;
unsigned long int *dest;
unsigned long int *source;
unsigned long int *range;
} map;
typedef struct {
unsigned long int seed;
unsigned long int range;
unsigned long int *min;
map **ruleList;
} mt_args;
unsigned long int remap(unsigned long int seed, map **remaps);
map *storeRules(FILE *input, char *row, int n);
void gotoMap(FILE *input, int n);
void *threadedRange(mt_args *args);
// del b: Lagra inte seeds. för varje seed, kör igenom alla maps. efter alla maps,
// spara siffran om den är lägre än tidigare.
// optimization ideas:
// Store rules as *array[7] of remapArrays[rules * 3 ints]
// ...and int len[7] that holds the length of each remap
// spawn thread per range
// ^ this is to avoid changing the logic to handle ranges lol
// lagra 7 map-pekare
// struct map: int len, dest[], source[], range[]
// len antal rules
// skapa gotoMap-funktion (rullar streamen till map n)
// skapa funktion för att mappa och returnera _en map_
// ^ kalla dessa 7 gånger
int main()
{
unsigned long int minimum = UINT_MAX;
unsigned long int seedRanges[SEEDS] = {0};
char row[250];
char c;
FILE *input;
input = fopen("./input", "r");
int seed = 0;
while (c = fgetc(input) != '\n') {
while (isdigit(c = fgetc(input))) {
seedRanges[seed] = seedRanges[seed] * 10 + (c - '0');
}
fseek(input, -1L, SEEK_CUR); // currently stepping two steps forward so yeah
if (seedRanges[seed] != 0) seed++;
}
map *ruleList[7]; // Get pointers to 7 populated ruleList
for (int i = 0; i < 7; i++) ruleList[i] = storeRules(input, row, i);
fclose(input);
/* Debug, print rules
for (int i = 0; i < 7; i++) {
for (int j = 0; j < ruleList[i]->len; j++) {
printf("%u %u %u\n", ruleList[i]->dest[j], ruleList[i]->source[j], ruleList[i]->range[j]);
}
}
*/
pthread_t *thread_id = malloc (sizeof(pthread_t) * 10);
unsigned long int smallest[10] = {0};
// for each seed-range pair, run remap for each seed
for (int i = 0; i < 19; i += 2) {
printf("%d\n", i);
// unsigned long int new;
mt_args *args = malloc(sizeof(mt_args));
args->seed = seedRanges[i];
args->range = seedRanges[i + 1];
args->min = &smallest[i / 2];
args->ruleList = ruleList;
pthread_create(&thread_id[i / 2], NULL, &threadedRange, args);
/*
for (int j = 0; j < seedRanges[i + 1]; j++) {
new = remap(seedRanges[i] + j, ruleList);
if (new < minimum) minimum = new;
}
*/
// printf("Range %u-%u done\n", seedRanges[i], seedRanges[i] + seedRanges[i + 1]);
// printf("min: %u\n", minimum);
// printf("new: %u\n", new);
}
for (int i = 0; i < 10; i++) {
printf("joining %d: \n", i);
pthread_join(thread_id[i], NULL);
printf("%u\n", smallest[i]);
}
for (int i = 0; i < 10; i++) {
if (smallest[i] < minimum) minimum = smallest[i];
}
printf("smallest: %u\n", minimum);
}
void *threadedRange(mt_args *args)
{
unsigned long int minimum = UINT_MAX;
unsigned long int new = 0;
// printf("seedstart: %u range: %u\n", args->seed, args->range);
for (unsigned long int i = 0; i < args->range; i++) {
new = remap(args->seed + i, args->ruleList);
// if (new == 0) printf("wtf %u\n", args->seed + i);
if (new < minimum) minimum = new;
}
args->min[0] = minimum;
}
// Change this function to take one seed, run through all remaps for it, then return value
unsigned long int remap(unsigned long int seed, map **remaps)
{
unsigned long int oldSeed = seed;
for (int i = 0; i < 7; i++) {
// printf("Dest: %u, Source: %u, range: %u\n", dest, source, range + 1);
for (int j = 0; j < remaps[i]->len; j++) {
if (seed >= remaps[i]->source[j] && seed <= remaps[i]->source[j] + remaps[i]->range[j]) {
//printf("Map %d: %u is in range, moving to %u\n", i + 1, seed, remaps[i]->dest[j] + seed - remaps[i]->source[j]);
seed = remaps[i]->dest[j] + seed - remaps[i]->source[j];
// if (seed == 0) printf("Seed %u became 0 on map %d\n", oldSeed, i);
break;
// printf("Seed %d: %u\n", i + 1, seedArray[i]);
// printf("seed found! next map %u\n", seed);
}
}
}
return seed;
}
map *storeRules(FILE *input, char *row, int n)
{
unsigned long int len = 0;
gotoMap(input, n);
while (fgets(row, 250, input) != NULL) {
if (strstr(row, "seeds:") || row[0] == '\n') break;
len++;
}
gotoMap(input, n);
map *ruleList = malloc(sizeof(unsigned long int) + 3 * sizeof(unsigned long int*));
ruleList->dest = calloc(len, sizeof(unsigned long int));
ruleList->source = calloc(len, sizeof(unsigned long int));
ruleList->range = calloc(len, sizeof(unsigned long int));
int i = 0;
while (fgets(row, 250, input) != NULL) {
if (strstr(row, "seeds:") || row[0] == '\n') break;
int j = 0;
while (!isdigit(row[j])) j++;
for (; isdigit(row[j]); j++) {
ruleList->dest[i] = ruleList->dest[i] * 10 + row[j] - '0';
}
while (!isdigit(row[j])) j++;
for (; isdigit(row[j]); j++) {
ruleList->source[i] = ruleList->source[i] * 10 + row[j] - '0';
}
while (!isdigit(row[j])) j++;
for (; isdigit(row[j]); j++) {
ruleList->range[i] = ruleList->range[i] * 10 + row[j] - '0';
}
i++;
}
ruleList->len = len;
return ruleList;
}
void gotoMap(FILE *input, int n)
{
char row[250];
rewind(input);
while (fgets(row, 250, input) != NULL) {
if (strstr(row, "map")) n--;
if (n < 0) break;
}
}