aoc_omni/c/2024/19/linen_layout.c

79 lines
1.8 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "../../lib/aoc.h"
#include "../../lib/hashmap.h"
typedef char Towel[10];
typedef struct Towels {
Towel towels[2000];
int towels_count;
AocHashmap *map;
} Towels;
bool towels_valid_design(Towels *t, char *design) {
if (strlen(design) == 0) return true;
for (int i = 0; i < t->towels_count; i++) {
if (strstr(design, t->towels[i]) == design) {
if (towels_valid_design(t, design + strlen(t->towels[i]))) return true;
}
}
return false;
}
long towels_valid_designs(Towels *t, char *design) {
AocHashmapNode *memo = aoc_hashmap_get(t->map, design);
if (memo != NULL) return *(long *)memo->value;
if (strlen(design) == 0) return 1;
long *valid_designs = malloc(sizeof(long));
for (int i = 0; i < t->towels_count; i++) {
if (strstr(design, t->towels[i]) == design) {
*valid_designs += towels_valid_designs(t, design + strlen(t->towels[i]));
}
}
aoc_hashmap_put(t->map, design, valid_designs);
return *valid_designs;
}
int main() {
char *line;
Towels towels;
towels.towels_count = 0;
towels.map = malloc(sizeof(AocHashmap));
for (int i = 0; i < AOC_HASHMAP_RADIX; i++) {
towels.map->buckets[i] = NULL;
}
line = aoc_read_line();
char *token = strtok(line, ", ");
while (token != NULL) {
strcpy(towels.towels[towels.towels_count++], token);
token = strtok(NULL, ", ");
}
aoc_read_line(); // blank line
int valid_single_designs = 0;
long valid_multi_designs = 0;
while ((line = aoc_read_line()) != NULL) {
if (towels_valid_design(&towels, line)) valid_single_designs++;
valid_multi_designs += towels_valid_designs(&towels, line);
}
printf("Part 1: %d\n", valid_single_designs);
printf("Part 2: %ld\n", valid_multi_designs);
aoc_hashmap_free(towels.map);
aoc_free();
exit(0);
}