#include #include #include #include #define DEFAULT_FILE "input.txt" #define STRBUF_LEN 300 #define ISDIGIT(X) (X >= '0' && X <= '9') #define ADVENT_MAP_PRINT(X) do {printf("Dest: %d Src: %d Len: %d\n", X.dest, X.src, X.len);} while (0); #define ADVENT_MAP_EQ(X,Y) (X.dest == Y.dest && X.src == Y.src && X.len == Y.len) /********************************************************/ // Linked List Functions /********************************************************/ // Node structure typedef struct ll_node { void *data; struct ll_node *next; } ll_node; // Linked list structure typedef struct linked_list { ll_node* head; } linked_list; void ll_init(linked_list* list) { list->head = NULL; } // Function to create a new node ll_node* ll_create_node(void *data) { ll_node* new_node = (ll_node*)malloc(sizeof(ll_node)); if (new_node != NULL) { new_node->data = data; new_node->next = NULL; } return new_node; } // Function to add a node to the beginning of the list void ll_prepend(linked_list* list, void *data) { ll_node* new_node = ll_create_node(data); if (new_node != NULL) { new_node->next = list->head; list->head = new_node; } } // Function to add a node to the end of the list void ll_append(linked_list* list, void *data) { ll_node* newNode = ll_create_node(data); if (newNode != NULL) { if (list->head == NULL) { list->head = newNode; } else { ll_node* current = list->head; while (current->next != NULL) { current = current->next; } current->next = newNode; } } } // Function to remove a node with a given value void ll_remove(linked_list* list, void *data, bool (*compare_function)(void *, void*)) { ll_node* current = list->head; ll_node* prev = NULL; while (current != NULL && !compare_function(current->data, data)) { prev = current; current = current->next; } if (current != NULL) { if (prev != NULL) { prev->next = current->next; } else { list->head = current->next; } free(current); } } // Function to free the memory used by the linked list void ll_free(linked_list* list) { ll_node* current = list->head; ll_node* next; while (current != NULL) { next = current->next; free(current->data); free(current); current = next; } list->head = NULL; } uint64_t ll_len(linked_list* list) { uint64_t len = 0; ll_node *current = list->head; while (current != NULL) { len++; current = current->next; } return len; } /********************************************************/ // Seeds /********************************************************/ typedef struct advent_map { uint64_t dest; uint64_t src; uint64_t len; } advent_map; uint64_t parse_num(char *str) { uint64_t num = 0; while (ISDIGIT(*str)) { num = (num * 10) + (*str - '0'); str++; } return num; } linked_list parse_seeds(char *str) { linked_list seeds; ll_init(&seeds); while (!ISDIGIT(*str)) str++; while (ISDIGIT(*str)) { uint64_t *seed = malloc(sizeof(uint64_t)); *seed = parse_num(str); ll_append(&seeds, seed); while (ISDIGIT(*str)) str++; if (*str == ' ') str++; } return seeds; } void print_seeds(linked_list *list) { ll_node* current = list->head; while (current != NULL) { printf("Num: %lud\n", *((uint64_t *)(current->data))); current = current->next; } printf("\n"); } uint64_t seed_min(linked_list *list) { ll_node* current = list->head; if (current == NULL) return 0; uint64_t current_val = *(uint64_t *)(current->data); uint64_t min = current_val; while (current != NULL) { current_val = *(uint64_t *)(current->data); if (current_val < min) min = current_val; current = current->next; } return min; } /********************************************************/ // Maps /********************************************************/ void parse_map(linked_list *map, FILE *file) { char *strbuf = malloc(sizeof(char) * STRBUF_LEN); char *str = strbuf; fgets(strbuf, STRBUF_LEN, file); while (ISDIGIT(*strbuf)) { str = strbuf; advent_map *map_node = malloc(sizeof(advent_map)); map_node->dest = parse_num(str); while (ISDIGIT(*str)) str++; str++; map_node->src = parse_num(str); while (ISDIGIT(*str)) str++; str++; map_node->len = parse_num(str); ll_append(map, map_node); if (!fgets(strbuf, STRBUF_LEN, file)) break; } } void print_map(linked_list *list) { ll_node* current = list->head; advent_map *m; while (current != NULL) { m = (advent_map *)(current->data); printf("dest: %lu src: %lu len: %lu\n", m->dest, m->src, m->len); current = current->next; } printf("\n"); } uint64_t translate(linked_list *map, uint64_t value) { ll_node *current_node = map->head; while (current_node != NULL) { advent_map *current_map = (advent_map *)current_node->data; if (value - current_map->src < current_map->len) { return current_map->dest + (value - current_map->src); } current_node = current_node->next; } return value; } void translate_all(linked_list *map, linked_list *seeds) { ll_node *current_node = seeds->head; while (current_node != NULL) { uint64_t current_int = *((uint64_t *)(current_node->data)); uint64_t translated_int = translate(map, current_int); *((uint64_t *)(current_node->data)) = translated_int; current_node = current_node->next; } } int main(int argc, char **argv) { // Get filename as an argument, if there is one char *path = (argc > 1) ? argv[1] : DEFAULT_FILE; if (!path) { printf("Requires input file.\n"); return 1; } FILE *file = fopen(path, "r"); char strbuf[STRBUF_LEN] = {0}; if (!file) { printf("Could not find file."); return 1; } linked_list seeds; linked_list seed_to_soil; linked_list soil_to_fertilizer; linked_list fertilizer_to_water; linked_list water_to_light; linked_list light_to_temperature; linked_list temperature_to_humidity; linked_list humidity_to_location; linked_list *maps[7] = {&seed_to_soil, &soil_to_fertilizer, &fertilizer_to_water, &water_to_light, &light_to_temperature, &temperature_to_humidity, &humidity_to_location }; uint64_t i = 0; for (i = 0; i < 7; i++) { ll_init(maps[i]); } fgets(strbuf, STRBUF_LEN, file); seeds = parse_seeds(strbuf); fgets(strbuf, STRBUF_LEN, file); for (i = 0; i < 7; i++) { fgets(strbuf, STRBUF_LEN, file); printf(strbuf); parse_map(maps[i], file); print_map(maps[i]); translate_all(maps[i], &seeds); } print_seeds(&seeds); uint64_t min = seed_min(&seeds); printf("Min: %lu\n", min); return 0; }