Files
advent-of-code-2023/day_5.c
2023-12-08 17:10:54 +01:00

165 lines
4.9 KiB
C

//
// Created by lennart on 12/7/23.
//
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <ctype.h>
#include "input_handler.h"
//region types
#define LIST_NAME IntList
#define LIST_PREFIX ilist
#define ELEMENT_TYPE unsigned int
#include "list.h"
typedef struct {
uint32_t source;
uint32_t destination;
uint32_t length;
} Range;
#define LIST_NAME RangeList
#define LIST_PREFIX rlist
#define ELEMENT_TYPE Range
#include "list.h"
typedef struct {
IntList *seeds;
RangeList *seed_to_soil;
RangeList *soil_to_fertilizer;
RangeList *fertilizer_to_water;
RangeList *water_to_light;
RangeList *light_to_temperature;
RangeList *temperature_to_humidity;
RangeList *humidity_to_location;
} Almanac;
//endregion types
Almanac* load_almanac(FILE *f);
RangeList* load_map(FILE *f, const char *name);
void almanac_free(Almanac *almanac);
int main() {
FILE *f = fopen("day_5.txt", "r");
if(f == NULL) {
fprintf(stderr, "Missing input file!\n");
exit(1);
}
Almanac *almanac = load_almanac(f);
// Part 1 - Iterate over each seed and transform number using first matching range for each map
uint32_t min_location = UINT32_MAX;
for(int i = 0; i < almanac->seeds->length; i++) {
uint32_t source = almanac->seeds->data[i];
for(int j = 0; j < 7; j++) {
RangeList ranges = * ((RangeList**) almanac)[j + 1];
for(int k = 0; k < ranges.length; k++) {
Range range = ranges.data[k];
if(source >= range.source && source < range.source + range.length) {
source = source - range.source + range.destination;
break;
}
}
}
if(source < min_location) {
min_location = source;
}
}
printf("Result #1: %u\n", min_location);
// Part 2
printf("Solving part 2.\nHold your horses... this might take a while.\n");
min_location = UINT32_MAX;
for(int i = 0; i < almanac->seeds->length; i += 2) {
uint32_t min = almanac->seeds->data[i];
uint32_t icount = almanac->seeds->data[i + 1];
for(int i2 = 0; i2 < icount; i2++) {
uint32_t source = min + i2;
for(int j = 0; j < 7; j++) {
RangeList ranges = * ((RangeList**) almanac)[j + 1];
for(int k = 0; k < ranges.length; k++) {
Range range = ranges.data[k];
if(source >= range.source && source < range.source + range.length) {
source = source - range.source + range.destination;
break;
}
}
}
if(source < min_location) {
min_location = source;
}
}
printf(".");
}
printf("\nResult #2: %u\n", min_location);
almanac_free(almanac);
fclose(f);
return 0;
}
Almanac* load_almanac(FILE *f) {
Almanac *almanac = malloc(sizeof (Almanac));
char *buffer = NULL;
int bufferLen;
// Load the seeds
read_line(f, &buffer, &bufferLen);
assert(strlen(buffer) > 7 && strncmp(buffer, "seeds: ", 7) == 0); // expect name prefix line
almanac->seeds = ilist_create(16);
char *cursor = &buffer[7];
while(*cursor != 0) {
if(!isdigit(*cursor) && cursor++) continue;
uint32_t seed = (uint32_t) strtoul(cursor, &cursor, 10);
ilist_add(almanac->seeds, seed);
}
read_line(f, &buffer, &bufferLen);
assert(strcmp(, "") == 0); // expect empty line at end
almanac->seed_to_soil = load_map(f, "seed-to-soil");
almanac->soil_to_fertilizer = load_map(f, "soil-to-fertilizer");
almanac->fertilizer_to_water = load_map(f, "fertilizer-to-water");
almanac->water_to_light = load_map(f, "water-to-light");
almanac->light_to_temperature = load_map(f, "light-to-temperature");
almanac->temperature_to_humidity = load_map(f, "temperature-to-humidity");
almanac->humidity_to_location = load_map(f, "humidity-to-location");
free(buffer);
return almanac;
}
RangeList* load_map(FILE *f, const char *name) {
RangeList *list = rlist_create(16);
char *buffer = NULL;
int bufferLen;
read_line(f, &buffer, &bufferLen);
assert(strncmp(buffer, name, strlen(name)) == 0);
while(!feof(f) && strcmp(read_line(f, &buffer, &bufferLen), "") != 0) {
Range range;
sscanf(buffer, "%u %u %u", &range.destination, &range.source, &range.length);
rlist_add(list, range);
}
free(buffer);
return list;
}
void almanac_free(Almanac *almanac) {
ilist_free(almanac->seeds);
rlist_free(almanac->seed_to_soil);
rlist_free(almanac->soil_to_fertilizer);
rlist_free(almanac->fertilizer_to_water);
rlist_free(almanac->water_to_light);
rlist_free(almanac->light_to_temperature);
rlist_free(almanac->temperature_to_humidity);
rlist_free(almanac->humidity_to_location);
free(almanac);
}