aoc

My solutions for the Advent of Code
git clone https://git.tronto.net/aoc
Download | Log | Files | Refs | README

10b.c (3405B)


      1 #include <stdio.h>
      2 
      3 #define N 1000
      4 #define set(i, j, c) if (newmap[i][j] == '.') newmap[i][j] = c;
      5 
      6 typedef enum { EAST, SOUTH, WEST, NORTH } direction_t;
      7 
      8 char map[N+2][N+2], newmap[N+2][N+2];
      9 int n, si, sj, count[26] = {0};
     10 direction_t sdir;
     11 
     12 void printmap(char m[][N+2]) {
     13 	for (int i = 1; i < n; i++) {
     14 		for (int j = 1; m[i][j] != 'B'; j++)
     15 			printf("%c", m[i][j]);
     16 		printf("\n");
     17 	}
     18 }
     19 
     20 void color_rl(direction_t dir, int i, int j) {
     21 	switch (dir) {
     22 	case EAST:
     23 		set(i-1, j, 'L');
     24 		set(i+1, j, 'R');
     25 		break;
     26 	case SOUTH:
     27 		set(i, j+1, 'L');
     28 		set(i, j-1, 'R');
     29 		break;
     30 	case WEST:
     31 		set(i-1, j, 'R');
     32 		set(i+1, j, 'L');
     33 		break;
     34 	case NORTH:
     35 		set(i, j+1, 'R');
     36 		set(i, j-1, 'L');
     37 		break;
     38 	default:
     39 		break;
     40 	}
     41 }
     42 
     43 direction_t firstdir(int i, int j) {
     44 	if (map[i][j+1] ==  '7' || map[i][j+1] == '-' || map[i][j+1] == 'J')
     45 		return EAST;
     46 	if (map[i+1][j] ==  'L' || map[i+1][j] == '|' || map[i+1][j] == 'J')
     47 		return SOUTH;
     48 	return WEST;
     49 }
     50 
     51 void advance(int *i, int *j, direction_t dir) {
     52 	if (dir == EAST) { (*j)++; }
     53 	else if (dir == SOUTH) { (*i)++; }
     54 	else if (dir == WEST) { (*j)--; }
     55 	else (*i)--;
     56 }
     57 
     58 direction_t newdir(int i, int j, direction_t dir) {
     59 	switch (map[i][j]) {
     60 	case '|':
     61 	case '-':
     62 		return dir;
     63 	case '7':
     64 		if (dir == EAST) return SOUTH;
     65 		if (dir == NORTH) return WEST;
     66 	case 'F':
     67 		if (dir == WEST) return SOUTH;
     68 		if (dir == NORTH) return EAST;
     69 	case 'J':
     70 		if (dir == EAST) return NORTH;
     71 		if (dir == SOUTH) return WEST;
     72 	case 'L':
     73 		if (dir == WEST) return NORTH;
     74 		if (dir == SOUTH) return EAST;
     75 	default:
     76 		printf("Error: dead path at (%d, %d)\n", i, j);
     77 		exit(1);
     78 	}
     79 	return EAST;
     80 }
     81 
     82 void walk_and_color_rl(char c) {
     83 	int i = si, j = sj;
     84 	direction_t dir = sdir;
     85 
     86 	newmap[i][j] = c;
     87 	color_rl(dir, i, j);
     88 	advance(&i, &j, dir);
     89 	for (; map[i][j] != 'S'; advance(&i, &j, dir)) {
     90 		newmap[i][j] = c;
     91 		color_rl(dir, i, j);
     92 		dir = newdir(i, j, dir);
     93 		color_rl(dir, i, j);
     94 	}
     95 	color_rl(dir, i, j);
     96 }
     97 
     98 void fill(int i, int j, char c) {
     99 	if (newmap[i][j] != '.' && newmap[i][j] != 'R' && newmap[i][j] != 'L')
    100 		return;
    101 
    102 	newmap[i][j] = c;
    103 	count[c-'a']++;
    104 	fill(i, j+1, c);
    105 	fill(i, j-1, c);
    106 	fill(i+1, j, c);
    107 	fill(i-1, j, c);
    108 }
    109 
    110 int main() {
    111 	/* Get input */
    112 	for (n = 1; fgets(&map[n][1], N, stdin) != NULL; n++) ;
    113 
    114 	/* Add borders, copy to newmap */
    115 	for (int i = 0; i < N+2; i++) {
    116 		for (int j = 0; j < N+2; j++) {
    117 			newmap[i][j] = map[i][j];
    118 			if (map[i][j] == 0 || map[i][j] == '\n')
    119 				newmap[i][j] = map[i][j] = 'B';
    120 		}
    121 	}
    122 
    123 	/* Find S and set the initial direction */
    124 	for (si = 1; si < n; si++)
    125 		for (sj = 1; map[si][sj] != 'B'; sj++)
    126 			if (map[si][sj] == 'S')
    127 				goto found_s;
    128 
    129 found_s:
    130 	/* Set the initial direction and walk the path mark it with X */
    131 	sdir = firstdir(si, sj);
    132 	walk_and_color_rl('X');
    133 
    134 	/* Replace the unnecessary pipe symbols with dots */
    135 	for (int i = 1; i < N; i++)
    136 		for (int j = 1; map[i][j] != 'B'; j++)
    137 			if (newmap[i][j] != 'X')
    138 				newmap[i][j] = '.';
    139 
    140 	/* Walk again the path and mark adjacent dots left and right */
    141 	walk_and_color_rl('Y');
    142 
    143 	/* Mark the remaining dots left and right */
    144 	for (int i = 1; i < n; i++)
    145 		for (int j = 1; newmap[i][j] != 'B'; j++)
    146 			if (newmap[i][j] == 'R' || newmap[i][j] == 'L')
    147 				fill(i, j, newmap[i][j] + 'a' - 'A');
    148 
    149 	printmap(newmap);
    150 	printf("r: %d\nl: %d\n", count['r'-'a'], count['l'-'a']);
    151 	printf("Check with the map printed above which one is 'inside'\n");
    152 	return 0;
    153 }