feat: add day 5
This commit is contained in:
165
day_5.c
165
day_5.c
@@ -3,21 +3,162 @@
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include "map.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() {
|
||||
Map *map = map_create();
|
||||
|
||||
map_put(map, 0x0, 1);
|
||||
map_put(map, 0x10, 2);
|
||||
|
||||
for(int i = 0; i < 10000; i++) {
|
||||
map_put(map, i, i + 1);
|
||||
FILE *f = fopen("day_5.txt", "r");
|
||||
if(f == NULL) {
|
||||
fprintf(stderr, "Missing input file!\n");
|
||||
exit(1);
|
||||
}
|
||||
// for(int i = 0; i < 10000; i++) {
|
||||
// assert(map_get(map, i) == i + 1);
|
||||
// }
|
||||
Almanac *almanac = load_almanac(f);
|
||||
|
||||
map_free(map);
|
||||
// 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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user