// // Created by liviu on 3/27/25. // #include #include #include #include typedef uint8_t u8; typedef int8_t i8; typedef uint16_t u16; typedef int16_t i16; typedef uint32_t u32; typedef int32_t i32; typedef uint64_t u64; typedef int64_t i64; struct pos { i32 row, col; }; struct pos add(struct pos a, struct pos b) { return (struct pos){a.row + b.row, a.col + b.col}; } struct pos sub(struct pos a, struct pos b) { return (struct pos){a.row - b.row, a.col - b.col}; } typedef struct pos data_type; const u32 data_size = sizeof(data_type); struct darr { u32 capacity; u32 len; data_type* data; u32 head; }; struct darr darr_ctor(const u32 capacity) { data_type* ptr = malloc(capacity * data_size); if (ptr == NULL) exit(1); return (struct darr) {capacity, 0, ptr, 0}; } void darr_dtor(const struct darr *_) { free(_->data); } void ensure_length(struct darr *dyn, const u32 len) { if (dyn->capacity >= len) return; struct darr next = darr_ctor(len * 2); memcpy(next.data, dyn->data, dyn->capacity * data_size); data_type* temp = next.data; next.data = dyn->data; dyn->data = temp; dyn->capacity = next.capacity; dyn->head = 0; darr_dtor(&next); } data_type* queue_index(const struct darr* q, const u32 i) { return &q->data[(q->head + i) % q->capacity]; } void enqueue(struct darr* queue, const data_type value) { ensure_length(queue, queue->len + 1); *queue_index(queue, queue->len) = value; queue->len++; } void deque(struct darr* queue) { if (queue->len == 0) exit(2); queue->len--; queue->head = (queue->head + 1) % queue->capacity; } #define NMAX 13 i32 maze[NMAX][NMAX] = { {-1, -1, -1, -1, 0, -1, 0, -1, 0, -1, -1, -1, -1}, {-1, -1, -1, -1, 0, -1, 0, -1, 0, -1, -1, -1, -1}, {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1}, {-1, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {-1, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {-1, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {-1, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -1}, {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1}, {-1, -1, -1, -1, 0, -1, 0, -1, 0, -1, -1, -1, -1}, {-1, -1, -1, -1, 0, -1, 0, -1, 0, -1, -1, -1, -1} }; u8 path[NMAX][NMAX]; u8* path_at(const struct pos* loc) { return &path[loc->row][loc->col]; } i32* maze_at(const struct pos* loc) { return &maze[loc->row][loc->col]; } struct pos directions[4] = { {0, 1}, {0, -1}, {1, 0}, {-1, 0}}; u8 in_bounds(const struct pos* p) { return p->row >= 0 && p->col >= 0 && p->row < NMAX && p->col < NMAX; } i32 bfs(const struct pos start, const struct pos finish) { struct darr queue = darr_ctor(100); memset(path, -1, NMAX * NMAX * sizeof(u8)); *path_at(&start) = 0; enqueue(&queue, start); while (queue.len) { const struct pos top = *queue_index(&queue, 0); deque(&queue); const u8 count = *path_at(&top); for (int i = 0; i < 4; i++) { const struct pos next = add(top, directions[i]); if (!in_bounds(&next)) continue; if (*maze_at(&next) == -1) continue; /* path is blocked */ if (*path_at(&next) <= count) continue; /* path was visited already */ *path_at(&next) = count + 1; enqueue(&queue, next); // print pos and status // printf("%d,%d,%d\n", next.row, next.col, *path_at(&next)); // if (memcmp(&next, &finish, data_size) == 0) goto die; } } die: darr_dtor(&queue); return *path_at(&finish) - *path_at(&start) + 1; } int main(int argc, char** argv) { i32 dist = bfs((const struct pos){4, 0}, (const struct pos){8, 0}); printf("Path length is %d\n", dist); for (u32 i = 0; i < NMAX; i++) { for (u32 j = 0; j < NMAX; j++) { printf("%d\t", path[i][j]); } printf("\n"); } return 0; }