Day18
This commit is contained in:
BIN
day18/c/day18
Executable file
BIN
day18/c/day18
Executable file
Binary file not shown.
229
day18/c/day18.c
Normal file
229
day18/c/day18.c
Normal file
@@ -0,0 +1,229 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CHARS_MAX 6
|
||||
#define MAX_BYTES 16*1024
|
||||
#define QUEUE_MAX 16*1024
|
||||
|
||||
const int directions[][2] = {
|
||||
{0, 1},
|
||||
{1, 0},
|
||||
{0, -1},
|
||||
{-1, 0}
|
||||
};
|
||||
|
||||
#define directions_len (sizeof(directions)/sizeof(directions[0]))
|
||||
|
||||
int main() {
|
||||
char *p, *buf, c;
|
||||
|
||||
buf = calloc(CHARS_MAX, sizeof(char));
|
||||
p = buf;
|
||||
|
||||
int (*bytes)[2] = calloc(MAX_BYTES, sizeof(bytes[0]));
|
||||
int byte_count = 0;
|
||||
|
||||
while ((c = getchar()) != EOF) {
|
||||
*p++ = c;
|
||||
if (c != '\n') {
|
||||
continue;
|
||||
}
|
||||
|
||||
p = buf;
|
||||
sscanf(p, "%i", &bytes[byte_count][0]);
|
||||
while(*p++ != ',');
|
||||
sscanf(p, "%i", &bytes[byte_count++][1]);
|
||||
|
||||
memset(buf, 0, CHARS_MAX);
|
||||
p = buf;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
int rows, colums, first_batch;
|
||||
// Sample vs real life
|
||||
if (byte_count < 1024) {
|
||||
rows = 7;
|
||||
colums = 7;
|
||||
first_batch = 12;
|
||||
} else {
|
||||
rows = 71;
|
||||
colums = 71;
|
||||
first_batch = 1024;
|
||||
}
|
||||
int **map = calloc(rows, sizeof(map[0]));
|
||||
for (int i = 0; i < rows; i++) {
|
||||
map[i] = calloc(colums, sizeof(map[0][0]));
|
||||
}
|
||||
|
||||
|
||||
// Task 1: First batch of bytes
|
||||
for (int i = 0; i < first_batch; i++) {
|
||||
map[bytes[i][1]][bytes[i][0]] = 1;
|
||||
}
|
||||
|
||||
// Shortest path search
|
||||
uint32_t **costs = calloc(rows, sizeof(costs[0]));
|
||||
for (int i = 0; i < rows; i++) {
|
||||
costs[i] = calloc(colums, sizeof(costs[0][0]));
|
||||
memset(costs[i], 255, colums * sizeof(costs[0][0]));
|
||||
}
|
||||
|
||||
int (*queue)[2] = calloc(QUEUE_MAX, sizeof(queue[0]));
|
||||
int queue_num = 1;
|
||||
// Start at 0,0
|
||||
queue[0][0] = 0;
|
||||
queue[0][1] = 0;
|
||||
costs[0][0] = 0;
|
||||
|
||||
while (queue_num > 0) {
|
||||
// Pop first
|
||||
int x = queue[0][0];
|
||||
int y = queue[0][1];
|
||||
uint32_t cost = costs[x][y];
|
||||
|
||||
if (x == rows - 1 && y == colums - 1) {
|
||||
printf("%u\n", cost);
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < queue_num - 1; i++) {
|
||||
queue[i][0] = queue[i+1][0];
|
||||
queue[i][1] = queue[i+1][1];
|
||||
}
|
||||
queue_num--;
|
||||
|
||||
// Check each direction
|
||||
for (int i = 0; i < directions_len; i++) {
|
||||
int dx = directions[i][0];
|
||||
int dy = directions[i][1];
|
||||
|
||||
int next_x = x + dx;
|
||||
int next_y = y + dy;
|
||||
|
||||
// Outside of map, into wall, or better path exists
|
||||
if (next_x < 0 || next_y < 0 || next_x >= rows || next_y >= colums || map[next_x][next_y] || costs[next_x][next_y] <= cost + 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Insert into queue
|
||||
uint32_t next_cost = cost + 1;
|
||||
costs[next_x][next_y] = next_cost;
|
||||
int insert_idx;
|
||||
for (insert_idx = 0; insert_idx < queue_num; insert_idx++) {
|
||||
int qx = queue[insert_idx][0];
|
||||
int qy = queue[insert_idx][1];
|
||||
if (costs[qx][qy] > next_cost) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = queue_num; j > insert_idx; j--) {
|
||||
queue[j][0] = queue[j-1][0];
|
||||
queue[j][1] = queue[j-1][1];
|
||||
}
|
||||
queue[insert_idx][0] = next_x;
|
||||
queue[insert_idx][1] = next_y;
|
||||
queue_num++;
|
||||
}
|
||||
}
|
||||
|
||||
// Second part
|
||||
for (int k = 1; k < byte_count; k++) {
|
||||
int **map = calloc(rows, sizeof(map[0]));
|
||||
for (int i = 0; i < rows; i++) {
|
||||
map[i] = calloc(colums, sizeof(map[0][0]));
|
||||
}
|
||||
for (int i = 0; i <= k; i++) {
|
||||
map[bytes[i][1]][bytes[i][0]] = 1;
|
||||
}
|
||||
uint32_t **costs = calloc(rows, sizeof(costs[0]));
|
||||
for (int i = 0; i < rows; i++) {
|
||||
costs[i] = calloc(colums, sizeof(costs[0][0]));
|
||||
memset(costs[i], 255, colums * sizeof(costs[0][0]));
|
||||
}
|
||||
|
||||
int (*queue)[2] = calloc(QUEUE_MAX, sizeof(queue[0]));
|
||||
int queue_num = 1;
|
||||
// Start at 0,0
|
||||
queue[0][0] = 0;
|
||||
queue[0][1] = 0;
|
||||
costs[0][0] = 0;
|
||||
|
||||
int path_found = 0;
|
||||
|
||||
while (queue_num > 0) {
|
||||
// Pop first
|
||||
int x = queue[0][0];
|
||||
int y = queue[0][1];
|
||||
uint32_t cost = costs[x][y];
|
||||
|
||||
if (x == rows - 1 && y == colums - 1) {
|
||||
path_found = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < queue_num - 1; i++) {
|
||||
queue[i][0] = queue[i+1][0];
|
||||
queue[i][1] = queue[i+1][1];
|
||||
}
|
||||
queue_num--;
|
||||
|
||||
// Check each direction
|
||||
for (int i = 0; i < directions_len; i++) {
|
||||
int dx = directions[i][0];
|
||||
int dy = directions[i][1];
|
||||
|
||||
int next_x = x + dx;
|
||||
int next_y = y + dy;
|
||||
|
||||
// Outside of map, into wall, or better path exists
|
||||
if (next_x < 0 || next_y < 0 || next_x >= rows || next_y >= colums || map[next_x][next_y] || costs[next_x][next_y] <= cost + 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Insert into queue
|
||||
uint32_t next_cost = cost + 1;
|
||||
costs[next_x][next_y] = next_cost;
|
||||
int insert_idx;
|
||||
for (insert_idx = 0; insert_idx < queue_num; insert_idx++) {
|
||||
int qx = queue[insert_idx][0];
|
||||
int qy = queue[insert_idx][1];
|
||||
if (costs[qx][qy] > next_cost) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = queue_num; j > insert_idx; j--) {
|
||||
queue[j][0] = queue[j-1][0];
|
||||
queue[j][1] = queue[j-1][1];
|
||||
}
|
||||
queue[insert_idx][0] = next_x;
|
||||
queue[insert_idx][1] = next_y;
|
||||
queue_num++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!path_found) {
|
||||
printf("%i,%i\n", bytes[k][0], bytes[k][1]);
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < rows; i++) {
|
||||
free(map[i]);
|
||||
free(costs[i]);
|
||||
}
|
||||
free(map);
|
||||
free(costs);
|
||||
}
|
||||
|
||||
free(bytes);
|
||||
for (int i = 0; i < rows; i++) {
|
||||
free(map[i]);
|
||||
free(costs[i]);
|
||||
}
|
||||
free(map);
|
||||
free(costs);
|
||||
}
|
||||
3450
day18/input.txt
Normal file
3450
day18/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
25
day18/sample.txt
Normal file
25
day18/sample.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
5,4
|
||||
4,2
|
||||
4,5
|
||||
3,0
|
||||
2,1
|
||||
6,3
|
||||
2,4
|
||||
1,5
|
||||
0,6
|
||||
3,3
|
||||
2,6
|
||||
5,1
|
||||
1,2
|
||||
5,5
|
||||
2,5
|
||||
6,5
|
||||
1,4
|
||||
0,4
|
||||
6,4
|
||||
1,1
|
||||
6,1
|
||||
1,0
|
||||
0,5
|
||||
1,6
|
||||
2,0
|
||||
Reference in New Issue
Block a user