mirror of
https://git.plasmaofthedawn.com/adventofcode.git
synced 2025-12-05 03:13:48 -06:00
225 lines
4.4 KiB
C
225 lines
4.4 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define BOARD_SIZE 141
|
|
|
|
#define CHEAT_LENGTH 20
|
|
|
|
#define IN_BOUND(x, y) (x < BOARD_SIZE && x >= 0 && y < BOARD_SIZE && y >= 0)
|
|
#define MIN(a,b) (((a)<(b))?(a):(b))
|
|
|
|
struct coordinate {
|
|
|
|
int x, y;
|
|
|
|
};
|
|
|
|
|
|
struct coordinate queue[10000];
|
|
int queue_len;
|
|
int queue_start;
|
|
|
|
char map[BOARD_SIZE][BOARD_SIZE];
|
|
int values[BOARD_SIZE][BOARD_SIZE];
|
|
|
|
struct coordinate cheat_deltas[10000];
|
|
int num_cheat_deltas;
|
|
|
|
|
|
int queue_pop(struct coordinate *coord) {
|
|
|
|
if (queue_len == 0) {
|
|
return -1;
|
|
}
|
|
|
|
memcpy(coord, &queue[queue_start], sizeof(struct coordinate));
|
|
|
|
queue_start++;
|
|
queue_len--;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
void queue_push(struct coordinate *coord) {
|
|
|
|
|
|
//printf("%d, %da\n", coord->x, coord->y);
|
|
|
|
memcpy(&queue[queue_start + queue_len], coord, sizeof(struct coordinate));
|
|
queue_len++;
|
|
|
|
}
|
|
|
|
|
|
void check_and_push(struct coordinate *coord, int depth) {
|
|
|
|
//printf("%d\n", depth);
|
|
|
|
if (!IN_BOUND(coord->x, coord->y) || map[coord->x][coord->y] == '#') {
|
|
return;
|
|
}
|
|
|
|
if (values[coord->x][coord->y] == 100000) {
|
|
//printf("%d\n", depth);
|
|
values[coord->x][coord->y] = depth + 1;
|
|
queue_push(coord);
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
int dfs(struct coordinate coord) {
|
|
|
|
queue_push(&coord);
|
|
values[coord.x][coord.y] = 0;
|
|
|
|
while (!queue_pop(&coord)) {
|
|
|
|
//printf("%d, %d!", coord.x, coord.y);
|
|
|
|
int value = values[coord.x][coord.y];
|
|
|
|
//printf("%d, %d: %d\n", coord.x, coord.y, values[coord.x][coord.y]);
|
|
|
|
coord.x++;
|
|
check_and_push(&coord, value);
|
|
coord.x -= 2;
|
|
check_and_push(&coord, value);
|
|
coord.x++;
|
|
|
|
coord.y++;
|
|
check_and_push(&coord, value);
|
|
coord.y -= 2;
|
|
check_and_push(&coord, value);
|
|
coord.y++;
|
|
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int cheats = 0;
|
|
|
|
int test_cheat(int x, int y, int value, int dist) {
|
|
int v;
|
|
if (IN_BOUND(x, y) && (map[x][y] == '.' || map[x][y] == 'E') && (v = values[x][y] - value) > dist) {
|
|
v -= dist;
|
|
//printf("cheat: %d\n", v, x, y);
|
|
|
|
if (v >= 100) {
|
|
cheats++;
|
|
}
|
|
|
|
return v;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int test_next(int x, int y, int value) {
|
|
//printf("%d, %d\n", value, values[x][y]);
|
|
return (IN_BOUND(x, y) && map[x][y] == '.' && values[x][y] - value == 1);
|
|
}
|
|
|
|
|
|
int find_cheat(int x, int y) {
|
|
|
|
printf("%d, %d ", x, y);
|
|
printf("%c\n", map[x][y]);
|
|
|
|
if (!IN_BOUND(x, y)) {
|
|
return 0;
|
|
}
|
|
|
|
|
|
int value = values[x][y];
|
|
int v;
|
|
|
|
for (int i = 0; i < num_cheat_deltas; i++) {
|
|
//printf("%d, %d\n", x + cheat_deltas[i].x, y + cheat_deltas[i].y);
|
|
test_cheat(x + cheat_deltas[i].x, y + cheat_deltas[i].y, value, abs(cheat_deltas[i].x) + abs(cheat_deltas[i].y));
|
|
}
|
|
|
|
if (test_next(x + 1, y, value)) {
|
|
return find_cheat(x + 1, y);
|
|
}
|
|
if (test_next(x - 1, y, value)) {
|
|
return find_cheat(x - 1, y);
|
|
}
|
|
if (test_next(x, y + 1, value)) {
|
|
return find_cheat(x, y + 1);
|
|
}
|
|
if (test_next(x, y - 1, value)) {
|
|
return find_cheat(x, y - 1);
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
// calc cheats
|
|
|
|
for (int x = -CHEAT_LENGTH; x <= CHEAT_LENGTH; x++) {
|
|
for (int y = -CHEAT_LENGTH; y <= CHEAT_LENGTH; y++) {
|
|
|
|
if (abs(x) + abs(y) <= CHEAT_LENGTH) {
|
|
//printf("%d, %d\n", x, y);
|
|
|
|
cheat_deltas[num_cheat_deltas].x = x;
|
|
cheat_deltas[num_cheat_deltas].y = y;
|
|
num_cheat_deltas++;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
//exit(0);
|
|
|
|
char *line_buf = NULL;
|
|
size_t buffer_size = 100;
|
|
|
|
for (int i = 0; i < BOARD_SIZE; i++) {
|
|
for (int j = 0; j < BOARD_SIZE; j++) {
|
|
map[i][j] = '.';
|
|
values[i][j] = 100000;
|
|
}
|
|
}
|
|
|
|
struct coordinate coords[10000];
|
|
int num_cords = 0;
|
|
|
|
|
|
struct coordinate start, end;
|
|
|
|
int y = 0;
|
|
while (getline(&line_buf, &buffer_size, stdin) > 0) {
|
|
printf(line_buf);
|
|
for (int x = 0; x < BOARD_SIZE; x++) {
|
|
map[x][y] = line_buf[x];
|
|
|
|
if (line_buf[x] == 'S') {
|
|
start.x = x;
|
|
start.y = y;
|
|
}
|
|
|
|
if (line_buf[x] == 'E') {
|
|
end.x = x;
|
|
end.y = y;
|
|
}
|
|
}
|
|
y++;
|
|
}
|
|
|
|
dfs(start);
|
|
find_cheat(start.x, start.y);
|
|
printf("res: %d", cheats);
|
|
}
|