2024-12-14 05:34:10 -06:00

170 lines
3.7 KiB
C

#include <stdint.h>
#include "parse.h"
#include "printf.h"
#include "memory.h"
#include "solution.h"
#include "cartesian.h"
struct solution_state _2024_day14_state = {0};
const char * parse_robot(const char * input, struct robot * robot)
{
input = parse_match(input, "p=");
input = parse_base10(input, &robot->x);
input = parse_skip(input, ',');
input = parse_base10(input, &robot->y);
input = parse_match(input, " v=");
input = parse_base10(input, &robot->dx);
input = parse_skip(input, ',');
input = parse_base10(input, &robot->dy);
input = parse_skip(input, '\n');
return input;
}
static inline int positive_modulus(int n, int d) {
return (n % d + d) % d;
}
void simulate_robot(struct robot * robot,
int width, int height,
int steps)
{
int x = robot->x + robot->dx * steps;
robot->x = positive_modulus(x, width);
int y = robot->y + robot->dy * steps;
robot->y = positive_modulus(y, height);
}
static int xy_to_quadrant(int x, int y, int width, int height)
{
int midx = width / 2;
int midy = height / 2;
if (x == midx || y == midy)
return -1;
return
(0b01 * (x > midx)) |
(0b10 * (y > midy));
}
static int flood_fill(char * visited,
int width, int height,
int x, int y)
{
int size = 1;
visited[y * width + x] = 0;
for (int i = 0; i < cartesian_neighbor_count; i++) {
int nx = x + cartesian_neighbor[i].x;
int ny = y + cartesian_neighbor[i].y;
char nc = visited[ny * width + nx];
if (cartesian_inside(width, height, nx, ny) && nc != 0) {
size += flood_fill(visited,
width, height,
nx, ny);
}
}
return size;
}
int64_t _2024_day14_part1(const char * input, int length)
{
const char * end = input + length;
//int width = 11;
//int height = 7;
int width = 101;
int height = 103;
int steps = 100;
int quadrant[4];
memory_set_int(quadrant, 0, 4);
while (input < end) {
struct robot robot;
input = parse_robot(input, &robot);
simulate_robot(&robot, width, height, steps);
int ix = xy_to_quadrant(robot.x, robot.y, width, height);
if (ix >= 0)
quadrant[ix] += 1;
}
int sum = quadrant[0];
for (int i = 1; i < 4; i++)
sum *= quadrant[i];
return sum;
}
int64_t _2024_day14_part2(const char * input, int length)
{
const char * end = input + length;
//int width = 11;
//int height = 7;
int width = 101;
int height = 103;
int robot_length = parse_height(input, length);
struct robot robot[robot_length];
_2024_day14_state.time = 0;
_2024_day14_state.robot = &robot[0];
_2024_day14_state.robot_length = robot_length;
int i = 0;
while (input < end) {
input = parse_robot(input, &robot[i++]);
}
_2024_day14_state.time = 0;
char visited[width * height];
int max_size = 0;
_2024_day14_state.max_size = max_size;
while (max_size < 200) {
int step = _2024_day14_state.step;
if (step == 0)
continue;
_2024_day14_state.time += step;
memory_set_char(visited, 0, width * height);
for (int i = 0; i < robot_length; i++) {
simulate_robot(&robot[i], width, height, step);
visited[robot[i].y * width + robot[i].x] = 1;
}
for (int i = 0; i < robot_length; i++) {
if (visited[robot[i].y * width + robot[i].x]) {
int size = flood_fill(visited,
width, height,
robot[i].x, robot[i].y);
_2024_day14_state.size = size;
if (size > max_size) {
max_size = size;
_2024_day14_state.max_size = max_size;
}
if (size > 200)
_2024_day14_state.step = 0;
}
}
}
return _2024_day14_state.time;
}