170 lines
3.7 KiB
C
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;
|
|
}
|