230 lines
6.2 KiB
C
230 lines
6.2 KiB
C
#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);
|
|
}
|