diff --git a/day11.c b/day11.c new file mode 100644 index 0000000..12369cf --- /dev/null +++ b/day11.c @@ -0,0 +1,187 @@ +#include +#include +#include +#include +#include + +#include "aoc.h" + +typedef enum { + MONKEY_OP_ADD, + MONKEY_OP_MUL, + MONKEY_OP_SQR +} MONKEY_OP; + +typedef struct { + int *items; + int item_count; + MONKEY_OP op; + int op_value; + int test_value; + int test_true; + int test_false; +} Monkey; + +typedef struct { + Monkey *monkeys; + int count; +} day11_Data; + +static int count_char(char *str, char target) +{ + int count = 0; + for (int i = 0; i < strlen(str); i++) { + count += str[i] == target; + } + return count; +} + +static void parse_items(char *items, int **result, int *result_count) +{ + int i = 0; + *result_count = count_char(items, ',')+1; + *result = malloc(*result_count * sizeof(int)); + for (char *num = strtok(items, ","); num; num = strtok(NULL, ",")) { + (*result)[i] = atoi(num+1); + i++; + } +} + +static void parse_operation(char *operation, MONKEY_OP *op, int *op_value) +{ + if (operation[4] == '+') { + *op = MONKEY_OP_ADD; + *op_value = atoi(operation + 6); + } else if (operation[4] == '*' && operation[6] == 'o') { + *op = MONKEY_OP_SQR; + } else { + *op = MONKEY_OP_MUL; + *op_value = atoi(operation + 6); + } +} + +static inline void apply_operation(uint64_t *value, MONKEY_OP op, int op_value) +{ + switch (op) { + case MONKEY_OP_ADD: + *value += op_value; + break; + case MONKEY_OP_MUL: + *value *= op_value; + break; + case MONKEY_OP_SQR: + *value *= *value; + break; + default: + printf("abort: %d\n", op); + fflush(stdout); + abort(); + } +} + +static void *day11_parse(char **lines, int line_count) +{ + day11_Data *data = malloc(sizeof(day11_Data)); + data->count = (line_count + 1)/7; + data->monkeys = malloc(data->count * sizeof(Monkey)); + + for (int i = 0; i < line_count; i+=7) { + Monkey *monkey = &data->monkeys[i/7]; + char *starting_items = lines[i+1] + 17; + char *operation = lines[i+2] + 19; + char *test_value = lines[i+3] + 21; + char *test_true = lines[i+4] + 29; + char *test_false = lines[i+5] + 30; + parse_items(starting_items, &monkey->items, &monkey->item_count); + parse_operation(operation, &monkey->op, &monkey->op_value); + monkey->test_value = atoi(test_value); + monkey->test_true = atoi(test_true); + monkey->test_false = atoi(test_false); + } + + return data; +} + +static uint64_t solve(day11_Data *data, int rounds, bool reduce_worry) +{ + int monkey_count = data->count; + + int inspections[monkey_count]; + for (int i = 0; i < data->count; i++) { + inspections[i] = 0; + } + + int total_item_count = 0; + for (int i = 0; i < monkey_count; i++) { + total_item_count += data->monkeys[i].item_count; + } + + size_t items[monkey_count][total_item_count]; + size_t item_counts[monkey_count]; + for (int i = 0; i < monkey_count; i++) { + Monkey *monkey = &data->monkeys[i]; + item_counts[i] = monkey->item_count; + for (int j = 0; j < monkey->item_count; j++) { + items[i][j] = monkey->items[j]; + } + } + + int modulo = 1; + for (int i = 0; i < monkey_count; i++) { + modulo *= data->monkeys[i].test_value; + } + + for (int round = 1; round <= rounds; round++) { + for (int i = 0; i < monkey_count; i++) { + Monkey *monkey = &data->monkeys[i]; + for (int j = 0; j < item_counts[i]; j++) { + uint64_t item_worry = items[i][j]; + apply_operation(&item_worry, monkey->op, monkey->op_value); + if (reduce_worry) { + item_worry /= 3; + } else { + item_worry %= modulo; + } + + int target_monkey; + if (item_worry % monkey->test_value == 0) { + target_monkey = monkey->test_true; + } else { + target_monkey = monkey->test_false; + } + + items[target_monkey][item_counts[target_monkey]++] = item_worry; + } + + inspections[i] += item_counts[i]; + item_counts[i] = 0; + } + + } + + uint64_t top_inspection1 = 0; + uint64_t top_inspection2 = 0; + for (int i = 0; i < monkey_count; i++) { + if (inspections[i] > top_inspection1) { + top_inspection2 = top_inspection1; + top_inspection1 = inspections[i]; + } else if (inspections[i] > top_inspection2) { + top_inspection2 = inspections[i]; + } + } + + return top_inspection1*top_inspection2; +} + +static void day11_part1(void *p) +{ + printf("%lu\n", solve(p, 20, true)); +} + + +static void day11_part2(void *p) +{ + printf("%lu\n", solve(p, 10000, false)); +} + +ADD_SOLUTION(11, day11_parse, day11_part1, day11_part2); diff --git a/main.c b/main.c index f97e1dd..97e6a30 100644 --- a/main.c +++ b/main.c @@ -18,6 +18,7 @@ #include "day8.c" #include "day9.c" #include "day10.c" +#include "day11.c" Solution *find_solution(int day) {