Day17 C
This commit is contained in:
BIN
day17/c/day17
Executable file
BIN
day17/c/day17
Executable file
Binary file not shown.
185
day17/c/day17.c
Normal file
185
day17/c/day17.c
Normal file
@@ -0,0 +1,185 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define LINE_MAX_LENGTH 256
|
||||
#define NUM_0_CHARCODE 48
|
||||
#define equal(a,b) ((a)[0] == (b)[0] && (a)[1] == (b)[1])
|
||||
#define MAX_NODES 128*1024
|
||||
#define MAX_PATH 1024
|
||||
#define BIT_0 0x0000001
|
||||
#define BIT_1 0x0000002
|
||||
#define BIT_2 0x0000004
|
||||
#define BIT_3 0x0000008
|
||||
|
||||
typedef struct node {
|
||||
int position[2];
|
||||
int weight;
|
||||
int dir[2];
|
||||
int forward_count;
|
||||
} node_t;
|
||||
|
||||
void insert_to_queue(node_t *nodes, int *nodes_num, node_t node);
|
||||
long dir_to_bit(int dir[2]);
|
||||
void set_tmp(node_t *tmp, int next_x, int next_y, uint8_t map[LINE_MAX_LENGTH][LINE_MAX_LENGTH], node_t curr, int next_dir[2], int fwd);
|
||||
void find_path(node_t *curr, int start[2], int finish[2], uint8_t map[LINE_MAX_LENGTH][LINE_MAX_LENGTH], int x, int y, int min_fwd, int max_fwd);
|
||||
|
||||
int main() {
|
||||
char *p, *buf, c;
|
||||
|
||||
buf = (char *)malloc(LINE_MAX_LENGTH);
|
||||
memset(buf, 0, LINE_MAX_LENGTH);
|
||||
p = buf;
|
||||
|
||||
uint8_t map[LINE_MAX_LENGTH][LINE_MAX_LENGTH];
|
||||
memset(map, 0, LINE_MAX_LENGTH * LINE_MAX_LENGTH * sizeof(uint8_t));
|
||||
int x = 0, y = 0;
|
||||
|
||||
while ((c = getchar()) != EOF) {
|
||||
*p++ = c;
|
||||
if (c == '\n') {
|
||||
p = buf;
|
||||
x = 0;
|
||||
|
||||
while (*p != '\n') {
|
||||
map[x][y] = *p - NUM_0_CHARCODE;
|
||||
p++;
|
||||
x++;
|
||||
}
|
||||
y++;
|
||||
memset(buf, 0, LINE_MAX_LENGTH);
|
||||
p = buf;
|
||||
}
|
||||
}
|
||||
|
||||
int start[2] = {0, 0};
|
||||
int finish[2] = {x - 1, y - 1};
|
||||
node_t curr;
|
||||
|
||||
find_path(&curr, start, finish, map, x, y, 0, 3);
|
||||
|
||||
printf("%i\n", curr.weight);
|
||||
|
||||
find_path(&curr, start, finish, map, x, y, 4, 10);
|
||||
|
||||
printf("%i\n", curr.weight);
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
void insert_to_queue(node_t *nodes, int *nodes_num, node_t node) {
|
||||
int inserted = 0;
|
||||
for (int i = 0; i < *nodes_num; i++) {
|
||||
if (node.weight < nodes[i].weight) {
|
||||
// Shift to the right
|
||||
for (int j = *nodes_num; j > i; j--) {
|
||||
memcpy(&nodes[j], &nodes[j-1], sizeof(node_t));
|
||||
}
|
||||
memcpy(&nodes[i], &node, sizeof(node_t));
|
||||
inserted = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!inserted) {
|
||||
memcpy(&nodes[*nodes_num], &node, sizeof(node_t));
|
||||
}
|
||||
(*nodes_num)++;
|
||||
}
|
||||
|
||||
long dir_to_bit(int dir[2]) {
|
||||
if (dir[0] == 1) {
|
||||
return BIT_0;
|
||||
}
|
||||
|
||||
if (dir[0] == -1) {
|
||||
return BIT_1;
|
||||
}
|
||||
|
||||
if (dir[1] == 1) {
|
||||
return BIT_2;
|
||||
}
|
||||
|
||||
return BIT_3;
|
||||
}
|
||||
|
||||
void set_tmp(node_t *tmp, int next_x, int next_y, uint8_t map[LINE_MAX_LENGTH][LINE_MAX_LENGTH], node_t curr, int next_dir[2], int fwd) {
|
||||
tmp->position[0] = next_x;
|
||||
tmp->position[1] = next_y;
|
||||
tmp->weight = curr.weight + map[next_x][next_y];
|
||||
tmp->dir[0] = next_dir[0];
|
||||
tmp->dir[1] = next_dir[1];
|
||||
tmp->forward_count = fwd ? curr.forward_count + 1 : 1;
|
||||
}
|
||||
|
||||
void find_path(node_t *curr, int start[2], int finish[2], uint8_t map[LINE_MAX_LENGTH][LINE_MAX_LENGTH], int x, int y, int min_fwd, int max_fwd) {
|
||||
node_t tmp;
|
||||
tmp.position[0] = start[0];
|
||||
tmp.position[1] = start[1];
|
||||
tmp.weight = 0;
|
||||
tmp.dir[0] = 1;
|
||||
tmp.dir[1] = 0;
|
||||
tmp.forward_count = 1;
|
||||
long visited[LINE_MAX_LENGTH][LINE_MAX_LENGTH];
|
||||
memset(visited, 0, LINE_MAX_LENGTH * LINE_MAX_LENGTH * sizeof(long));
|
||||
|
||||
node_t *nodes = (node_t*)malloc(MAX_NODES * sizeof(node_t));
|
||||
memset(nodes, 0, MAX_NODES * sizeof(node_t));
|
||||
int nodes_num = 1;
|
||||
memcpy(&nodes[0], &tmp, sizeof(node_t));
|
||||
int next_x, next_y, next_dir[2];
|
||||
for (;;) {
|
||||
// Pop first node
|
||||
memcpy(curr, &nodes[0], sizeof(node_t));
|
||||
|
||||
if (equal(curr->position, finish) && curr->forward_count >= min_fwd) {
|
||||
break;
|
||||
}
|
||||
// Shift entries
|
||||
for (int i = 0; i < nodes_num - 1; i++) {
|
||||
memcpy(&nodes[i], &nodes[i+1], sizeof(node_t));
|
||||
}
|
||||
nodes_num--;
|
||||
|
||||
// Check forward direction
|
||||
if (curr->forward_count != max_fwd) {
|
||||
next_dir[0] = curr->dir[0];
|
||||
next_dir[1] = curr->dir[1];
|
||||
next_x = curr->position[0] + next_dir[0];
|
||||
next_y = curr->position[1] + next_dir[1];
|
||||
|
||||
if (next_x >= 0 && next_x < x && next_y >= 0 && next_y < y && !(visited[next_x][next_y] & (dir_to_bit(next_dir) << (curr->forward_count * 4)))) {
|
||||
visited[next_x][next_y] |= (dir_to_bit(next_dir) << (curr->forward_count * 4));
|
||||
set_tmp(&tmp, next_x, next_y, map, *curr, next_dir, 1);
|
||||
insert_to_queue(nodes, &nodes_num, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
next_dir[0] = curr->dir[0] == 0 ? 1 : 0;
|
||||
next_dir[1] = curr->dir[1] == 0 ? 1 : 0;
|
||||
next_x = curr->position[0] + next_dir[0];
|
||||
next_y = curr->position[1] + next_dir[1];
|
||||
if (curr->forward_count >= min_fwd && next_x >= 0 && next_x < x && next_y >= 0 && next_y < y && !(visited[next_x][next_y] & (dir_to_bit(next_dir) << (max_fwd * 4)))) {
|
||||
visited[next_x][next_y] |= (dir_to_bit(next_dir) << (max_fwd * 4));
|
||||
set_tmp(&tmp, next_x, next_y, map, *curr, next_dir, 0);
|
||||
insert_to_queue(nodes, &nodes_num, tmp);
|
||||
}
|
||||
|
||||
next_dir[0] = curr->dir[0] == 0 ? -1 : 0;
|
||||
next_dir[1] = curr->dir[1] == 0 ? -1 : 0;
|
||||
next_x = curr->position[0] + next_dir[0];
|
||||
next_y = curr->position[1] + next_dir[1];
|
||||
if (curr->forward_count >= min_fwd && next_x >= 0 && next_x < x && next_y >= 0 && next_y < y && !(visited[next_x][next_y] & (dir_to_bit(next_dir) << (max_fwd * 4)))) {
|
||||
visited[next_x][next_y] |= (dir_to_bit(next_dir) << (max_fwd * 4));
|
||||
set_tmp(&tmp, next_x, next_y, map, *curr, next_dir, 0);
|
||||
insert_to_queue(nodes, &nodes_num, tmp);
|
||||
}
|
||||
|
||||
if (nodes_num == 0) {
|
||||
printf("No path to end\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(nodes);
|
||||
}
|
||||
Reference in New Issue
Block a user