1
0

Compare commits

...

10 Commits

Author SHA1 Message Date
9890e141f2 solve day 11 2022-12-11 15:42:53 +02:00
869259ef4e solve day 10 2022-12-11 02:59:49 +02:00
2c2c4ccfa9 solve day 9 2022-12-11 01:05:37 +02:00
344124eebb solve day 8 2022-12-10 23:26:47 +02:00
25d56534c9 solve day 7 2022-12-08 21:55:45 +02:00
bd9cf44c2d solve day 6 2022-12-06 22:58:18 +02:00
78dc6e8d2c solve day 5 2022-12-05 19:33:25 +02:00
db68cca73e create vec.h 2022-12-05 17:37:00 +02:00
441471ae48 solve day 4 2022-12-05 16:43:56 +02:00
750ada0c1d solve day 3 2022-12-05 16:43:56 +02:00
16 changed files with 1299 additions and 30 deletions

View File

@ -1,4 +1,4 @@
main: main.c
main: main.c day*.c vec.h aoc.h point.h
gcc -o main main.c -lcurl
run: main

2
aoc.h
View File

@ -3,7 +3,7 @@
#include <stdbool.h>
typedef int (*solution_cb)(void*);
typedef void (*solution_cb)(void*);
typedef void* (*parse_cb)(char** lines, int count);
typedef struct {
int day;

13
day1.c
View File

@ -16,7 +16,8 @@ typedef struct {
size_t count;
} Data;
static void *day1_parse(char **lines, int line_count) {
static void *day1_parse(char **lines, int line_count)
{
int elf_indexes[300] = { 0 };
int elf_count = 1;
for (int i = 1; i < line_count; i++) {
@ -45,7 +46,8 @@ static void *day1_parse(char **lines, int line_count) {
return data;
}
static int day1_part1(void *p) {
static void day1_part1(void *p)
{
Data *data = (Data*)p;
int max_calories = 0;
for (int i = 0; i < data->count; i++) {
@ -55,10 +57,11 @@ static int day1_part1(void *p) {
}
max_calories = MAX(max_calories, calories);
}
return max_calories;
printf("%d\n", max_calories);
}
static int day1_part2(void *p) {
static void day1_part2(void *p)
{
Data *data = (Data*)p;
int max_calories1 = 0;
int max_calories2 = 0;
@ -79,7 +82,7 @@ static int day1_part2(void *p) {
max_calories3 = calories;
}
}
return max_calories1 + max_calories2 + max_calories3;
printf("%d\n", max_calories1 + max_calories2 + max_calories3);
}
ADD_SOLUTION(1, day1_parse, day1_part1, day1_part2);

126
day10.c Normal file
View File

@ -0,0 +1,126 @@
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "aoc.h"
typedef enum {
INST_TYPE_NOOP,
INST_TYPE_ADD,
} INST_TYPE;
typedef struct {
INST_TYPE type;
int amount;
} Instruction;
typedef struct {
Instruction *instructions;
int count;
} day10_Data;
static void *day10_parse(char **lines, int line_count)
{
day10_Data *data = malloc(sizeof(day10_Data));
data->count = line_count;
data->instructions = malloc(line_count * sizeof(Instruction));
for (int i = 0; i < line_count; i++) {
char *line = lines[i];
Instruction *inst = &data->instructions[i];
if (!strcmp(line, "noop")) {
inst->type = INST_TYPE_NOOP;
} else { // addx
inst->type = INST_TYPE_ADD;
inst->amount = atoi(line + 5);
}
}
return data;
}
static void day10_part1(void *p)
{
day10_Data *data = p;
int regx = 1;
int result = 0;
int inst_idx = 0;
int cycle = 0;
int add_timer = 0;
bool add_started = false;
while (inst_idx < data->count) {
Instruction *inst = &data->instructions[inst_idx];
if (!add_started) {
if (inst->type == INST_TYPE_NOOP) {
inst_idx++;
} else if (inst->type == INST_TYPE_ADD) {
add_started = true;
add_timer = 2;
}
}
cycle++;
if ((cycle - 20) % 40 == 0 && cycle <= 220) {
result += cycle*regx;
}
if (add_started) {
add_timer--;
if (add_timer == 0) {
add_started = false;
regx += inst->amount;
inst_idx++;
}
}
}
printf("%d\n", result);
}
static void day10_part2(void *p)
{
day10_Data *data = p;
int regx = 1;
int inst_idx = 0;
int cycle = 0;
int add_timer = 0;
bool add_started = false;
while (inst_idx < data->count) {
Instruction *inst = &data->instructions[inst_idx];
if (!add_started) {
if (inst->type == INST_TYPE_NOOP) {
inst_idx++;
} else if (inst->type == INST_TYPE_ADD) {
add_started = true;
add_timer = 2;
}
}
if (abs(cycle % 40 - regx) <= 1) {
printf("#");
} else {
printf(".");
}
cycle++;
if (add_started) {
add_timer--;
if (add_timer == 0) {
add_started = false;
regx += inst->amount;
inst_idx++;
}
}
if (cycle % 40 == 0) {
printf("\n");
}
}
}
ADD_SOLUTION(10, day10_parse, day10_part1, day10_part2);

187
day11.c Normal file
View File

@ -0,0 +1,187 @@
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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);

41
day2.c
View File

@ -2,34 +2,32 @@
#include <stdlib.h>
#include "aoc.h"
#include "vec.h"
typedef struct {
char you, opponent;
} Round;
typedef struct {
Round *rounds;
size_t count;
} day2_Data;
static void *day2_parse(char **lines, int line_count) {
day2_Data *data = calloc(1, sizeof(day2_Data));
data->count = line_count;
data->rounds = calloc(line_count, sizeof(Round));
static void *day2_parse(char **lines, int line_count)
{
Vec *vec = vec_malloc(line_count);
for (int i = 0; i < line_count; i++) {
data->rounds[i].opponent = lines[i][0];
data->rounds[i].you = lines[i][2];
Round *round = malloc(sizeof(Round));
round->opponent = lines[i][0];
round->you = lines[i][2];
vec_push(vec, round);
}
return data;
return vec;
}
static int day2_part1(void *p) {
day2_Data *data = (day2_Data*)p;
static void day2_part1(void *p)
{
Vec *rounds = p;
int result = 0;
for (int i = 0; i < data->count; i++) {
Round *round = &data->rounds[i];
for (int i = 0; i < rounds->count; i++) {
Round *round = rounds->data[i];
char you = round->you;
char opponent = round->opponent;
@ -51,14 +49,15 @@ static int day2_part1(void *p) {
result += 6;
}
}
return result;
printf("%d\n", result);
}
static int day2_part2(void *p) {
day2_Data *data = (day2_Data*)p;
static void day2_part2(void *p)
{
Vec *data = p;
int result = 0;
for (int i = 0; i < data->count; i++) {
Round *round = &data->rounds[i];
Round *round = data->data[i];
char you = round->you;
char opponent = round->opponent;
@ -82,7 +81,7 @@ static int day2_part2(void *p) {
result += 6;
}
}
return result;
printf("%d\n", result);
}
ADD_SOLUTION(2, day2_parse, day2_part1, day2_part2);

94
day3.c Normal file
View File

@ -0,0 +1,94 @@
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "aoc.h"
#include "vec.h"
static void *day3_parse(char **lines, int line_count)
{
Vec *vec = vec_malloc(line_count);
for (size_t i = 0; i < line_count; i++) {
vec_push(vec, lines[i]);
}
return vec;
}
static bool contains(char needle, char* haystack, size_t len)
{
for (size_t i = 0; i < len; i++) {
if (haystack[i] == needle) {
return true;
}
}
return false;
}
static char find_common(char *str1, char* str2, size_t len)
{
for (size_t i = 0; i < len; i++) {
if (contains(str1[i], str2, len)) {
return str1[i];
}
}
return 0;
}
static int get_priority(char c)
{
if ('a' <= c && c <= 'z') {
return (c - 'a') + 1;
} else if ('A' <= c && c <= 'Z') {
return (c - 'A') + 27;
}
return 0;
}
static void day3_part1(void *p)
{
Vec *vec = p;
int result = 0;
for (size_t i = 0; i < vec->count; i++) {
char *b = vec->data[i];
int size = strlen(b);
char common = find_common(b, b + size/2, size/2);
if (common) {
result += get_priority(common);
} else {
fprintf(stderr, "Unknown common char at line: %zu\n", i+1);
}
}
printf("%d\n", result);
}
static void day3_part2(void *p)
{
Vec *vec = p;
int result = 0;
for (size_t i = 0; i < vec->count; i+=3) {
char *b1 = vec->data[i+0];
char *b2 = vec->data[i+1];
char *b3 = vec->data[i+2];
int size1 = strlen(b1);
int size2 = strlen(b2);
int size3 = strlen(b3);
bool found = false;
for (size_t j = 0; j < size1; j++) {
char c = b1[j];
if (contains(c, b2, size2) && contains(c, b3, size3)) {
result += get_priority(c);
found = true;
break;
}
}
if (!found) {
fprintf(stderr, "Unknown common char at line: %zu-%zu\n", i+1, i+3);
}
}
printf("%d\n", result);
}
ADD_SOLUTION(3, day3_parse, day3_part1, day3_part2);

78
day4.c Normal file
View File

@ -0,0 +1,78 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include "aoc.h"
#include "vec.h"
typedef struct {
int from, to;
} Range;
typedef struct {
Range first;
Range second;
} DoubleRange;
static inline void day4_parse_range(Range *range, char *s)
{
range->from = atoi(strsep(&s, "-"));
range->to = atoi(strsep(&s, "-"));
}
static void day4_parse_line(DoubleRange *double_range, char *line)
{
char *line_copy = strdup(line);
char *line_copy_start = line_copy;
day4_parse_range(&double_range->first, strsep(&line_copy, ","));
day4_parse_range(&double_range->second, strsep(&line_copy, ","));
free(line_copy_start);
}
static void *day4_parse(char **lines, int line_count)
{
Vec *vec = vec_malloc(line_count);
for (size_t i = 0; i < line_count; i++) {
DoubleRange *double_range = malloc(sizeof(DoubleRange));
vec_push(vec, double_range);
day4_parse_line(double_range, lines[i]);
}
return vec;
}
static void day4_part1(void *p)
{
Vec *vec = p;
int result = 0;
for (int i = 0; i < vec->count; i++) {
DoubleRange *double_range = vec->data[i];
Range *range1 = &double_range->first;
Range *range2 = &double_range->second;
if ((range1->from <= range2->from && range1->to >= range2->to) ||
(range2->from <= range1->from && range2->to >= range1->to)) {
result++;
}
}
printf("%d\n", result);
}
static void day4_part2(void *p)
{
Vec *vec = p;
int result = 0;
for (int i = 0; i < vec->count; i++) {
DoubleRange *double_range = vec->data[i];
Range *range1 = &double_range->first;
Range *range2 = &double_range->second;
if ((range1->from <= range2->from && range1->to >= range2->to) ||
(range2->from <= range1->from && range2->to >= range1->to) ||
MIN(range1->to, range2->to) >= MAX(range1->from, range2->from)) {
result++;
}
}
printf("%d\n", result);
}
ADD_SOLUTION(4, day4_parse, day4_part1, day4_part2);

165
day5.c Normal file
View File

@ -0,0 +1,165 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include "aoc.h"
#include "vec.h"
typedef struct {
int from, to, amount;
} Move;
typedef struct {
Vec *towers;
Vec *moves;
} day5_Data;
static Move* day5_parse_move(char *line)
{
char* line_copy = strdup(line);
char* line_copy_original = line_copy;
strsep(&line_copy, " ");
char* amount = strsep(&line_copy, " ");
strsep(&line_copy, " ");
char* from = strsep(&line_copy, " ");
strsep(&line_copy, " ");
char* to = strsep(&line_copy, " ");
Move *move = malloc(sizeof(Move));
move->amount = atoi(amount);
move->from = atoi(from)-1;
move->to = atoi(to)-1;
free(line_copy);
return move;
}
static void *day5_parse(char **lines, int line_count)
{
int tower_count = 0;
int max_tower_height;
for (int i = 0; i < line_count; i++) {
if (lines[i][0] == '\0') {
max_tower_height = i-1;
break;
}
tower_count = MAX(tower_count, (strlen(lines[i])+1)/4);
}
int move_count = line_count - max_tower_height - 2;
Vec *moves = vec_malloc(move_count);
for (int i = 0; i < move_count; i++) {
char *line = lines[max_tower_height+2+i];
vec_push(moves, day5_parse_move(line));
}
Vec *towers = vec_malloc(tower_count);
for (int i = 0; i < tower_count; i++) {
char* tower = calloc(26, sizeof(char));
vec_push(towers, tower);
}
for (int i = max_tower_height-1; i >= 0; i--) {
char* line = lines[i];
int line_size = strlen(line);
for (int j = 0; j < tower_count; j++) {
int index = j*4 + 1;
if (index >= line_size) break;
if (line[index] == ' ') continue;
char* tower = towers->data[j];
tower[max_tower_height-i-1] = line[index];
}
}
day5_Data *data = malloc(sizeof(day5_Data));
data->moves = moves;
data->towers = towers;
return data;
}
static void do_move(char **towers, int *tower_sizes, int from, int to)
{
int from_size = tower_sizes[from];
int to_size = tower_sizes[to];
towers[to][to_size] = towers[from][from_size-1];
tower_sizes[from]--;
tower_sizes[to]++;
}
static void do_move_many(char **towers, int *tower_sizes, int from, int to, int amount)
{
int from_size = tower_sizes[from];
int to_size = tower_sizes[to];
memcpy(towers[to] + to_size, towers[from] + from_size - amount, amount);
tower_sizes[from] -= amount;
tower_sizes[to] += amount;
}
static char* form_answer(char **towers, int tower_count, int *tower_sizes)
{
char *answer = malloc(tower_count + 1);
answer[tower_count] = '\0';
for (int i = 0; i < tower_count; i++) {
char *tower = towers[i];
answer[i] = tower[tower_sizes[i]-1];
}
return answer;
}
static void day5_part1(void *p)
{
day5_Data *data = p;
int tower_count = data->towers->count;
char *towers[tower_count];
int tower_sizes[tower_count];
for (int i = 0; i < tower_count; i++) {
towers[i] = calloc(26, sizeof(char));
memcpy(towers[i], data->towers->data[i], 26);
tower_sizes[i] = 0;
for (int j = 0; j < 26; j++) {
if (towers[i][j] == 0) break;
tower_sizes[i]++;
}
}
for (int i = 0; i < data->moves->count; i++) {
Move *move = data->moves->data[i];
for (int j = 0; j < move->amount; j++) {
do_move(towers, tower_sizes, move->from, move->to);
}
}
printf("%s\n", form_answer(towers, tower_count, tower_sizes));
}
static void day5_part2(void *p)
{
day5_Data *data = p;
int tower_count = data->towers->count;
char *towers[tower_count];
int tower_sizes[tower_count];
for (int i = 0; i < tower_count; i++) {
towers[i] = calloc(26, sizeof(char));
memcpy(towers[i], data->towers->data[i], 26);
tower_sizes[i] = 0;
for (int j = 0; j < 26; j++) {
if (towers[i][j] == 0) break;
tower_sizes[i]++;
}
}
for (int i = 0; i < data->moves->count; i++) {
Move *move = data->moves->data[i];
do_move_many(towers, tower_sizes, move->from, move->to, move->amount);
}
printf("%s\n", form_answer(towers, tower_count, tower_sizes));
}
ADD_SOLUTION(5, day5_parse, day5_part1, day5_part2);

56
day6.c Normal file
View File

@ -0,0 +1,56 @@
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "aoc.h"
#define MESSAGE_LENGTH 14
static void *day6_parse(char **lines, int line_count)
{
return lines[0];
}
static void day6_part1(void *p)
{
char *msg = p;
int n = strlen(msg);
for (int i = 3; i < n; i++) {
char c1 = msg[i-3];
char c2 = msg[i-2];
char c3 = msg[i-1];
char c4 = msg[i-0];
if (c1 != c2 && c1 != c3 && c1 != c4 &&
c2 != c3 && c2 != c4 &&
c3 != c4) {
printf("%d\n", i+1);
break;
}
}
}
static bool is_start_of_message(char *str)
{
for (int i=0; i < MESSAGE_LENGTH - 1; i++) {
for (int j=i+1; j < MESSAGE_LENGTH; j++) {
if (str[i] == str[j]) {
return false;
}
}
}
return true;
}
static void day6_part2(void *p)
{
char *msg = p;
int n = strlen(msg);
for (int i = 0; i < n-13; i++) {
if (is_start_of_message(msg+i)) {
printf("%d\n", i+14);
break;
}
}
}
ADD_SOLUTION(6, day6_parse, day6_part1, day6_part2);

166
day7.c Normal file
View File

@ -0,0 +1,166 @@
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <sys/param.h>
#include "aoc.h"
#include "vec.h"
#define CD_CMD "$ cd"
#define LS_CMD "$ ls"
#define TOTAL_FS_SIZE 70000000
#define UPDATE_SIZE 30000000
struct TreeNode {
char *name;
struct TreeNode *parent;
struct TreeNode **children;
size_t children_count;
size_t size;
};
static struct TreeNode *append_node(struct TreeNode *parent, char *child_name, size_t size)
{
struct TreeNode *new_child = calloc(1, sizeof(struct TreeNode));
new_child->parent = parent;
new_child->name = child_name;
new_child->size = size;
parent->children = realloc(parent->children, sizeof(struct TreeNode*)*(parent->children_count+1));
parent->children[parent->children_count] = new_child;
parent->children_count++;
return new_child;
}
static struct TreeNode *get_or_append_child(struct TreeNode *parent, char *child_name)
{
for (int i = 0; i < parent->children_count; i++) {
struct TreeNode *child = parent->children[i];
if (strcmp(child->name, child_name) == 0) {
return child;
}
}
return append_node(parent, child_name, -1);
}
static int find_char(char *haystack, char needle) {
int n = strlen(haystack);
for (int i = 0; i < n; i++) {
if (haystack[i] == needle) {
return i;
}
}
return -1;
}
static void populate_directory_sizes(struct TreeNode *start)
{
struct TreeNode *current = start;
while (current != start->parent) {
bool is_explored = true;
for (int i = 0; i < current->children_count; i++) {
struct TreeNode *child = current->children[i];
if (child->size == -1) {
current = child;
is_explored = false;
break;
}
}
if (is_explored) {
current->size = 0;
for (int i = 0; i < current->children_count; i++) {
current->size += current->children[i]->size;
}
current = current->parent;
}
}
}
static void *day7_parse(char **lines, int line_count)
{
struct TreeNode *root = calloc(1, sizeof(struct TreeNode));
root->name = "/";
struct TreeNode *current = root;
for (int i = 0; i < line_count; i++) {
char *line = lines[i];
if (strncmp(line, CD_CMD, sizeof(CD_CMD)-1) == 0) {
char *dir_name = line + sizeof(CD_CMD);
if (strncmp(dir_name, "/", 1) == 0) {
current = root;
} else if (strncmp(dir_name, "..", 2) == 0) {
current = current->parent;
} else {
current = get_or_append_child(current, dir_name);
}
} else if (strncmp(line, LS_CMD, sizeof(LS_CMD)) == 0) {
continue;
} else {
if (strncmp(line, "dir", 3) == 0) {
char *dir_name = line + 4;
get_or_append_child(current, dir_name);
} else {
int sep = find_char(line, ' ');
char *child_name = line + sep + 1;
line[sep] = '\0';
int size = strtol(line, NULL, 10);
line[sep] = ' ';
append_node(current, child_name, size);
}
}
}
return root;
}
static void day7_part1(void *p)
{
struct TreeNode *root = p;
populate_directory_sizes(root);
int result = 0;
Vec *stack = vec_malloc(10);
vec_push(stack, root);
while (stack->count > 0) {
struct TreeNode *node = vec_pop(stack);
if (node->size <= 100000 && node->children_count > 0) {
result += node->size;
}
for (int i = 0; i < node->children_count; i++) {
vec_push(stack, node->children[i]);
}
}
printf("%d\n", result);
}
static void day7_part2(void *p)
{
struct TreeNode *root = p;
populate_directory_sizes(root);
int needed_space = UPDATE_SIZE - (TOTAL_FS_SIZE - root->size);
int result = INT_MAX;
Vec *stack = vec_malloc(10);
vec_push(stack, root);
while (stack->count > 0) {
struct TreeNode *node = vec_pop(stack);
if (node->size >= needed_space && node->children_count > 0) {
result = MIN(result, node->size);
}
for (int i = 0; i < node->children_count; i++) {
vec_push(stack, node->children[i]);
}
}
printf("%d\n", result);
}
ADD_SOLUTION(7, day7_parse, day7_part1, day7_part2);

119
day8.c Normal file
View File

@ -0,0 +1,119 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include "aoc.h"
typedef struct {
uint8_t **data;
size_t width, height;
} day8_Map;
static void *day8_parse(char **lines, int line_count)
{
day8_Map *map = malloc(sizeof(day8_Map));
map->height = line_count;
map->width = strlen(lines[0]);
map->data = malloc(map->height*sizeof(uint8_t*));
for (int y = 0; y < map->height; y++) {
map->data[y] = malloc(map->width*sizeof(uint8_t));
for (int x = 0; x < map->width; x++) {
map->data[y][x] = lines[y][x] - '0';
}
}
return map;
}
static bool is_visible_horizontal(day8_Map *map, uint8_t value, int x0, int x1, int y)
{
for (int xi = x0; xi < x1; xi++) {
if (map->data[y][xi] >= value) return false;
}
return true;
}
static bool is_visible_vertical(day8_Map *map, uint8_t value, int x, int y0, int y1)
{
for (int yi = y0; yi < y1; yi++) {
if (map->data[yi][x] >= value) return false;
}
return true;
}
static bool is_visible(day8_Map *map, int x, int y) {
uint8_t current = map->data[y][x];
return is_visible_horizontal (map, current, x+1, map->width, y) ||
is_visible_horizontal(map, current, 0, x, y) ||
is_visible_vertical (map, current, x, y+1, map->height) ||
is_visible_vertical (map, current, x, 0, y);
}
static int get_horizontal_edge(day8_Map *map, uint8_t value, int x0, int x1, int y)
{
if (x0 <= x1) {
for (int xi = x0; xi <= x1; xi++) {
if (map->data[y][xi] >= value) return xi;
}
} else {
for (int xi = x0; xi >= x1; xi--) {
if (map->data[y][xi] >= value) return xi;
}
}
return x1;
}
static int get_vertical_edge(day8_Map *map, uint8_t value, int x, int y0, int y1)
{
if (y0 <= y1) {
for (int yi = y0; yi <= y1; yi++) {
if (map->data[yi][x] >= value) return yi;
}
} else {
for (int yi = y0; yi >= y1; yi--) {
if (map->data[yi][x] >= value) return yi;
}
}
return y1;
}
static int get_score(day8_Map *map, int x, int y) {
uint8_t value = map->data[y][x];
int right_edge = get_horizontal_edge(map, value, x+1, map->width-1, y);
int left_edge = get_horizontal_edge(map, value, x-1, 0 , y);
int bottom_edge = get_vertical_edge (map, value, x, y+1, map->height-1);
int top_edge = get_vertical_edge (map, value, x, y-1, 0);
return (right_edge - x) * (x - left_edge) * (bottom_edge - y) * (y - top_edge);
}
static void day8_part1(void *p)
{
day8_Map *map = p;
int result = map->height * map->width - (map->height-2) * (map->width-2);
for (int y = 1; y < map->height-1; y++) {
for (int x = 1; x < map->width-1; x++) {
result += is_visible(map, x, y);
}
}
printf("%d\n", result);
}
static void day8_part2(void *p)
{
day8_Map *map = p;
int result = 0;
for (int y = 1; y < map->height-1; y++) {
for (int x = 1; x < map->width-1; x++) {
result = MAX(result, get_score(map, x, y));
}
}
printf("%d\n", result);
}
ADD_SOLUTION(8, day8_parse, day8_part1, day8_part2);

213
day9.c Normal file
View File

@ -0,0 +1,213 @@
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <sys/param.h>
#include "aoc.h"
#include "point.h"
typedef enum {
MOVE_DIR_UP,
MOVE_DIR_DOWN,
MOVE_DIR_LEFT,
MOVE_DIR_RIGHT,
} MOVE_DIR;
typedef struct {
MOVE_DIR dir;
int count;
} RopeMove;
typedef struct {
RopeMove *moves;
int count;
} day9_Data;
static MOVE_DIR parse_move_dir(char dir)
{
switch (dir) {
case 'R': return MOVE_DIR_RIGHT;
case 'L': return MOVE_DIR_LEFT;
case 'U': return MOVE_DIR_UP;
case 'D': return MOVE_DIR_DOWN;
}
abort();
}
static void *day9_parse(char **lines, int line_count)
{
day9_Data *data = malloc(sizeof(day9_Data));
data->moves = malloc(line_count * sizeof(RopeMove));
data->count = line_count;
for (int i = 0; i < line_count; i++) {
char *line = lines[i];
RopeMove *move = &data->moves[i];
move->dir = parse_move_dir(line[0]);
move->count = atoi(line+2);
}
return data;
}
static int sign(int x)
{
return x > 0 ? 1 : -1;
}
static void get_bounding_box(day9_Data *moves, int *ox, int *oy, int *width, int *height)
{
int minx = 0, maxx = 0;
int miny = 0, maxy = 0;
int x = 0, y = 0;
for (int i = 0; i < moves->count; i++) {
RopeMove *move = &moves->moves[i];
switch (move->dir) {
case MOVE_DIR_UP:
y -= move->count;
break;
case MOVE_DIR_DOWN:
y += move->count;
break;
case MOVE_DIR_LEFT:
x -= move->count;
break;
case MOVE_DIR_RIGHT:
x += move->count;
break;
}
minx = MIN(x, minx);
maxx = MAX(x, maxx);
miny = MIN(y, miny);
maxy = MAX(y, maxy);
}
*ox = -minx;
*oy = -miny;
*width = maxx - minx + 1;
*height = maxy - miny + 1;
}
static void get_move_direction(MOVE_DIR dir, int *dx, int *dy)
{
switch (dir) {
case MOVE_DIR_UP:
*dy = -1;
break;
case MOVE_DIR_DOWN:
*dy = 1;
break;
case MOVE_DIR_LEFT:
*dx = -1;
break;
case MOVE_DIR_RIGHT:
*dx = 1;
break;
}
}
static void follow_point(Point *tail, Point *head)
{
int diffx = abs(head->x - tail->x);
int diffy = abs(head->y - tail->y);
if (diffx > 1 || diffy > 1) {
if (diffx + diffy > 2) {
tail->x += sign(head->x - tail->x);
tail->y += sign(head->y - tail->y);
} else if (diffx > 1) {
tail->x += sign(head->x - tail->x);
} else if (diffy > 1) {
tail->y += sign(head->y - tail->y);
}
}
}
static void day9_part1(void *p)
{
day9_Data *moves = p;
int ox, oy, width, height;
get_bounding_box(moves, &ox, &oy, &width, &height);
bool map[width][height];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
map[x][y] = false;
}
}
map[ox][oy] = true;
Point head = { 0, 0 };
Point tail = { 0, 0 };
for (int i = 0; i < moves->count; i++) {
RopeMove *move = &moves->moves[i];
int dx = 0, dy = 0;
get_move_direction(move->dir, &dx, &dy);
for (int j = 0; j < move->count; j++) {
head.x += dx;
head.y += dy;
follow_point(&tail, &head);
map[tail.x+ox][tail.y+oy] = true;
}
}
int result = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
result += map[x][y];
}
}
printf("%d\n", result);
}
static void day9_part2(void *p)
{
day9_Data *moves = p;
int ox, oy, width, height;
get_bounding_box(moves, &ox, &oy, &width, &height);
bool map[width][height];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
map[x][y] = false;
}
}
map[ox][oy] = true;
int rope_size = 10;
Point rope[rope_size];
for (int i = 0; i < rope_size; i++) {
rope[i].x = 0;
rope[i].y = 0;
}
for (int i = 0; i < moves->count; i++) {
RopeMove *move = &moves->moves[i];
int dx = 0, dy = 0;
get_move_direction(move->dir, &dx, &dy);
for (int _ = 0; _ < move->count; _++) {
Point *head = &rope[0];
head->x += dx;
head->y += dy;
for (int j = 1; j < rope_size; j++) {
follow_point(&rope[j], &rope[j-1]);
}
Point *tail = &rope[rope_size-1];
map[tail->x+ox][tail->y+oy] = true;
}
}
int result = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
result += map[x][y];
}
}
printf("%d\n", result);
}
ADD_SOLUTION(9, day9_parse, day9_part1, day9_part2);

15
main.c
View File

@ -10,6 +10,15 @@
#include "day1.c"
#include "day2.c"
#include "day3.c"
#include "day4.c"
#include "day5.c"
#include "day6.c"
#include "day7.c"
#include "day8.c"
#include "day9.c"
#include "day10.c"
#include "day11.c"
Solution *find_solution(int day)
{
@ -154,8 +163,10 @@ int main(int argc, char** argv) {
void* parsed = solution->parse(lines, line_count);
printf("part1: %d\n", solution->part1(parsed));
printf("part2: %d\n", solution->part2(parsed));
printf("part1:\n");
solution->part1(parsed);
printf("part2:\n");
solution->part2(parsed);
return 0;
}

8
point.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef POINT_H_
#define POINT_H_
typedef struct {
int x, y;
} Point;
#endif //POINT_H_

44
vec.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef VEC_H_
#define VEC_H_
#include <stdlib.h>
#include <assert.h>
typedef struct {
int count;
int capacity;
void **data;
} Vec;
static inline Vec *vec_malloc(size_t capacity)
{
Vec *vec = (Vec*)malloc(sizeof(Vec));
vec->count = 0;
vec->capacity = capacity;
vec->data = (void**)malloc(capacity * sizeof(void*));
return vec;
}
static inline void vec_push(Vec *vec, void* value)
{
if (vec->count >= vec->capacity) {
vec->capacity = (vec->capacity + 1) * 2;
vec->data = (void**)realloc(vec->data, vec->capacity * sizeof(void*));
}
vec->data[vec->count++] = value;
}
static inline void *vec_pop(Vec* vec)
{
vec->count--;
return vec->data[vec->count];
}
static inline void vec_free(Vec *v)
{
free(v->data);
free(v);
}
#endif //VEC_H_