#include #include #include #include #include #include struct grid { char** A; int x, y; }; void* xrealloc(void* ptr, size_t size) { if (size == 0) { size = 1; } ptr = realloc(ptr, size); if (ptr == NULL) { fprintf(stderr, "fatal: alloc(%zd) failed", size); exit(1); } return ptr; } int readfile(const char* filename, struct grid* out) { FILE *fp = fopen(filename, "r"); if (fp == NULL) { perror("fopen"); exit(1); } int len = 0; int cap = 100; char* data = xrealloc(NULL, cap); for (;;) { if (len >= cap) { cap *= 2; data = xrealloc(data, cap); } int c = fgetc(fp); if (c == -1) { break; } data[len] = c; len++; } int i, nl=0; for (i = 0; i < len; i++) { if (data[i] == '\n') { nl++; } } // split on newlines char** lines = xrealloc(NULL, nl * sizeof(char*)); char* p = data; int mincol = INT_MAX; i = 0; while (p != NULL && p < data+len) { lines[i++] = p; char* q = memchr(p, '\n', (data+len)-p); if (!q) { break; // TODO: final line? } int col = q - p; if (mincol > col && col > 0) { mincol = col; } p = q+1; // skip newline } out->A = lines; out->x = mincol; out->y = nl; return 0; } inline bool inbounds(struct grid *g, int x, int y) { return (0 <= x && x < g->x && 0 <= y && y < g->y); } struct step_r { int x, y, dx, dy; bool ok; }; struct step_r step(struct grid *g, int x, int y, int dx, int dy) { struct step_r r = {0}; if (!inbounds(g, x, y)) { return r; } // if there is nothing in front of you, step forward if (!inbounds(g, x+dx, y+dy) || g->A[y+dy][x+dx] != '#') { r.x = x+dx; r.y = y+dy; r.dx = dx; r.dy = dy; r.ok = true; return r; } else { // if there is something in front of you, turn right r.x = x; r.y = y; r.dx = -dy; r.dy = dx; r.ok = true; return r; } } struct point { int x, y; }; struct point startingPoint(struct grid *g) { int x, y; for (y = 0; y < g->y; y++) for (x = 0; x < g->x; x++) { if (g->A[y][x] == '^') { struct point r = {x, y}; return r; } } struct point r = {-1,-1}; return r; } int solve(struct grid *g) { struct point start = startingPoint(g); int x = start.x, y = start.y; int count = 0; int dx = 0, dy = -1; // up while(inbounds(g, x, y)) { if (g->A[y][x] != 'x') { count++; } g->A[y][x] = 'x'; struct step_r r = step(g, x, y, dx, dy); if (r.ok != true) { break; } x = r.x; y = r.y; dx = r.dx; dy = r.dy; } g->A[start.y][start.x] = '^'; printf("%d\n", count); return 0; } // returns whether the chosen grid will cause the guard to get stuck in a loop bool loops(struct grid *g, struct point start, uint8_t* state) { int x = start.x; int y = start.y; int dx = 0, dy = -1; // up int stride = g->x; //printf("loops(%d,%d)\n", x,y); while(inbounds(g, x, y)) { uint8_t dir = 15; if (dx == 1) { dir = 1; } else if (dx == -1) { dir = 2; } else if (dy == 1) { dir = 4; } else if (dy == -1) { dir = 8; } uint8_t *s = &state[y*stride + x]; if ((*s & dir) != 0) { // revisited a state, loop! return true; } *s |= dir; struct step_r r = step(g, x, y, dx, dy); if (r.ok != true) { // step failed, no loop return false; } x = r.x; y = r.y; dx = r.dx; dy = r.dy; } // left the map, no loop return false; } int solve2(struct grid *g) { int count = 0; int ox, oy; // obstacle coords struct point p = startingPoint(g); size_t state_size = g->x * g->y * sizeof(uint8_t); uint8_t *state = xrealloc(NULL, state_size); for (oy = 0; oy < g->y; oy++) for (ox = 0; ox < g->x; ox++) { int c = g->A[oy][ox]; if (c != '#' && c != '^') { g->A[oy][ox] = '#'; memset(state, 0, state_size); if (loops(g, p, state)) { count++; } g->A[oy][ox] = c; } } free(state); printf("%d\n", count); return 0; } int main() { struct grid g; //readfile("sample1.in", &g); readfile("input", &g); printf("%d %d\n", g.x, g.y); solve(&g); //printf("%s", g.A[0]); solve2(&g); }