176 lines
4.2 KiB
C
176 lines
4.2 KiB
C
#define _GNU_SOURCE
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <omp.h>
|
|
|
|
#define DIMENSION_MAX 512
|
|
#define abs(a) ((a) < 0 ? (-(a)) : (a))
|
|
|
|
typedef enum {
|
|
EMPTY,
|
|
OBSTRUCTION
|
|
} tile_t;
|
|
|
|
const int directions[][2] = {
|
|
{0, 1},
|
|
{1, 0},
|
|
{0, -1},
|
|
{-1, 0},
|
|
};
|
|
|
|
#define directions_len (sizeof(directions) / sizeof(directions[0]))
|
|
|
|
int update(int pos[2], int dir[2], int* dir_idx, tile_t **map, int rows, int cols, int** visited, int* count);
|
|
void next_dir(int dir[2], int *dir_idx);
|
|
|
|
int main() {
|
|
char c;
|
|
|
|
|
|
tile_t **map = calloc(DIMENSION_MAX, sizeof(map[0]));
|
|
int rows = 0, columns = 0, i = 0;
|
|
|
|
map[rows] = calloc(DIMENSION_MAX, sizeof(map[0][0]));
|
|
|
|
int pos[2] = { 0 };
|
|
int dir[2] = { 0 };
|
|
int dir_idx = 0;
|
|
int mypos[2] = { 0 };
|
|
int mydir[2] = { 0 };
|
|
int mydir_idx = 0;
|
|
|
|
while ((c = getchar()) != EOF) {
|
|
switch (c) {
|
|
case '.':
|
|
map[rows][i] = EMPTY;
|
|
break;
|
|
case '#':
|
|
map[rows][i] = OBSTRUCTION;
|
|
break;
|
|
case '>':
|
|
mypos[0] = rows;
|
|
mypos[1] = i;
|
|
mydir[0] = 0;
|
|
mydir[1] = 1;
|
|
mydir_idx = 0;
|
|
break;
|
|
case '^':
|
|
pos[0] = rows;
|
|
pos[1] = i;
|
|
dir[0] = -1;
|
|
dir[1] = 0;
|
|
dir_idx = 3;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
i++;
|
|
if (c != '\n') {
|
|
continue;
|
|
}
|
|
columns = i - 1;
|
|
|
|
rows++;
|
|
map[rows] = calloc(DIMENSION_MAX, sizeof(map[0][0]));
|
|
i = 0;
|
|
}
|
|
|
|
int **visited = calloc(rows, sizeof(visited[0]));
|
|
for (i = 0; i < columns; i++) {
|
|
visited[i] = calloc(columns, sizeof(visited[0][0]));
|
|
}
|
|
|
|
int start[5] = {pos[0], pos[1], dir[0], dir[1], dir_idx};
|
|
int move_count = 0;
|
|
while (update(pos, dir, &dir_idx, map, rows, columns, visited, &move_count));
|
|
|
|
int count = 0;
|
|
for (i = 0; i < rows; i++) {
|
|
for (int j = 0; j < columns; j++) {
|
|
count += visited[i][j];
|
|
}
|
|
}
|
|
|
|
int count2 = 0;
|
|
for (i = 0; i < rows; i++) {
|
|
for (int j = 0; j < columns; j++) {
|
|
if (map[i][j] == EMPTY && visited[i][j] && !(i == start[0] && j == start[1])) {
|
|
int **tmp = calloc(rows, sizeof(tmp[0]));
|
|
for (int k = 0; k < rows; k++) {
|
|
tmp[k] = calloc(columns, sizeof(tmp[0][0]));
|
|
}
|
|
pos[0] = start[0];
|
|
pos[1] = start[1];
|
|
dir[0] = start[2];
|
|
dir[1] = start[3];
|
|
dir_idx = start[4];
|
|
move_count = 0;
|
|
map[i][j] = OBSTRUCTION;
|
|
int result;
|
|
while((result = update(pos, dir, &dir_idx, map, rows, columns, tmp, &move_count)) == 1);
|
|
if (result == 2) {
|
|
count2++;
|
|
}
|
|
map[i][j] = EMPTY;
|
|
for (int k = 0; k < rows; k++) {
|
|
free(tmp[k]);
|
|
}
|
|
free(tmp);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < rows + 1; i++) {
|
|
free(map[i]);
|
|
}
|
|
free(map);
|
|
|
|
|
|
for (i = 0; i < columns; i++) {
|
|
free(visited[i]);
|
|
}
|
|
free(visited);
|
|
|
|
printf("%i\n", count);
|
|
printf("%i\n", count2);
|
|
}
|
|
|
|
int update(int pos[2], int dir[2], int* dir_idx, tile_t **map, int rows, int cols, int** visited, int *count) {
|
|
int y = pos[0] + dir[0];
|
|
int x = pos[1] + dir[1];
|
|
|
|
// Exiting map
|
|
if (y < 0 || x < 0 || y >= rows || x >= cols) {
|
|
return 0;
|
|
}
|
|
|
|
switch (map[y][x]) {
|
|
case OBSTRUCTION:
|
|
next_dir(dir, dir_idx);
|
|
break;
|
|
case EMPTY:
|
|
pos[0] = y;
|
|
pos[1] = x;
|
|
visited[y][x] = 1;
|
|
break;
|
|
}
|
|
(*count)++;
|
|
|
|
// Looping
|
|
if (*count > cols * rows * 4) {
|
|
return 2;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
void next_dir(int dir[2], int *dir_idx) {
|
|
(*dir_idx)++;
|
|
if (*dir_idx == directions_len) {
|
|
*dir_idx = 0;
|
|
}
|
|
|
|
dir[0] = directions[*dir_idx][0];
|
|
dir[1] = directions[*dir_idx][1];
|
|
}
|