advent-of-code-2024/day-14/main.c

169 lines
4.3 KiB
C

#include "aoc.h"
typedef struct {
i32 x, y;
i32 vx, vy;
} Robot;
static void
parse_pair(str s, i32 *x, i32 *y, Arena arena) {
s = str_sub(s, 2, s.len);
str lhs, rhs;
str_split(s, STR(","), &lhs, &rhs);
*x = (i32) parse_i64(lhs, arena);
*y = (i32) parse_i64(rhs, arena);
}
static Robot
parse_robot(str line, Arena arena) {
str p, v;
str_split(line, STR(" "), &p, &v);
Robot robot;
parse_pair(p, &robot.x, &robot.y, arena);
parse_pair(v, &robot.vx, &robot.vy, arena);
return robot;
}
static void
dump_grid(Arena arena, Robot *robots, isize count, int width, int height) {
u8 *grid = ARENA_ALLOC_ARRAY(&arena, u8, width * height);
for (isize i = 0; i < count; i++) {
Robot *r = &robots[i];
grid[r->y * width + r->x]++;
}
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
u8 count = grid[y * width + x];
if (count == 0) {
putchar('.');
} else {
putchar('0' + count);
}
}
putchar('\n');
}
}
static void
step(Robot *robots, isize count, int width, int height) {
for (isize i = 0; i < count; i++) {
Robot *r = &robots[i];
r->x = (r->x + r->vx + width) % width;
r->y = (r->y + r->vy + height) % height;
}
}
static bool
has_tree(u8 *grid, int width, int height) {
for (int x = 0; x < width; x++) {
i32 consecutive = 0;
for (int y = 1; y < height; y++) {
if (grid[y * width + x] && grid[(y - 1) * width + x]) {
consecutive++;
} else {
consecutive = 0;
}
if (consecutive >= width / 4) {
return true;
}
}
}
return false;
}
static f32
compute_entropy(u8 *grid, int width, int height) {
i32 counts[256] = {0};
for (int i = 0; i < width * height; i++) {
counts[grid[i]]++;
}
f32 entropy = 0.0f;
for (int i = 0; i < 256; i++) {
if (counts[i]) {
f32 prob = (f32) counts[i] / (f32) (width * height);
entropy -= prob * log2f(prob);
}
}
return entropy;
}
int main(int argc, char **argv) {
Arena *arena = make_arena(Megabytes(1));
Tokens lines = read_lines(arena, argv[1]);
int count = lines.len;
bool is_example = true;
Robot *robots = ARENA_ALLOC_ARRAY(arena, Robot, lines.len);
for (isize i = 0; i < lines.len; i++) {
robots[i] = parse_robot(str_trim(lines.tokens[i]), *arena);
if (robots[i].x >= 11) {
is_example = false;
}
}
int width = is_example ? 11 : 101;
int height = is_example ? 7 : 103;
ASSERT(width % 2 == 1);
ASSERT(height % 2 == 1);
/* dump_grid(*arena, robots, count, width, height); */
/* puts(""); */
i64 second = 0;
for (int i = 0; i < 100; i++) {
step(robots, count, width, height);
second++;
}
int cx = width / 2;
int cy = height / 2;
i64 counts[4] = {0};
for (isize i = 0; i < count; i++) {
Robot *r = &robots[i];
if (r->x != width / 2 && r->y != height / 2) {
int qx = r->x < cx ? 0 : 1;
int qy = r->y < cy ? 0 : 1;
counts[qy * 2 + qx]++;
}
}
i64 part_1 = counts[0] * counts[1] * counts[2] * counts[3];
printf("%ld\n", part_1);
// Part 2
u8 *grid = ARENA_ALLOC_ARRAY(arena, u8, width * height);
f32 best = 1.0f;
i32 best_second = 0;
i64 part_2 = 0;
for (;;) {
step(robots, count, width, height);
second++;
memset(grid, 0, width * height);
for (isize i = 0; i < count; i++) {
Robot *r = &robots[i];
grid[r->y * width + r->x]++;
}
#if 0
f32 entropy = compute_entropy(grid, width, height);
if (entropy < best) {
best = entropy;
best_second = second;
printf("%ld %f\n", second, entropy);
dump_grid(*arena, robots, count, width, height);
puts("--------------------");
}
#else
if (has_tree(grid, width, height)) {
printf("Tree detected on second %ld\n", second);
part_2 = second;
break;
}
#endif
}
dump_grid(*arena, robots, count, width, height);
printf("%ld\n", part_2);
}