#include #include #include #include // Check if a tree is newly seen, by being taller than max or not // // If it is seen, update max. // // If the tree is seen, and has not been seen before, return 1 // Otherwise return 0 int tree_seen(int * max, unsigned char * tree) { int height = (*tree & 0x7F) - '0'; int seen = 0; if (height > *max) { if (!(*tree & 0x80u)) { *tree |= 0x80u; ++seen; } *max = height; } return seen; } // Check the number of seen trees in a forest int forest_seen(unsigned char * forest, int rows, int cols) { int i, j, max, seen = 0; // For each row... for (i = 0; i < rows; ++i) { // Check which trees can be newly seen from the left for (j = 0, max = -1; j < cols - 1 && max < 9; ++j) { seen += tree_seen(&max, forest + i * cols + j); } // Check which trees can be newly seen from the right for (j = cols - 2, max = -1; j >= 0 && max < 9; --j) { seen += tree_seen(&max, forest + i * cols + j); } } // For each column... for (j = 0; j < cols - 1; ++j) { // Check which trees can be newly seen from the top for (i = 0, max = -1; i < rows && max < 9; ++i) { seen += tree_seen(&max, forest + i * cols + j); } // Check which trees can be newly seen from the bottom for (i = rows - 1, max = -1; i >= 0 && max < 9; --i) { seen += tree_seen(&max, forest + i * cols + j); } } return seen; } int main() { int cols = 0, rows = 0; char * forest; // Read first line forest = malloc(BUFSIZ); if (!fgets(forest, BUFSIZ, stdin)) { fprintf(stderr, "Need more input!\n"); return -1; } cols = strlen(forest); if (cols < 2 || forest[cols - 1] != '\n') { fprintf(stderr, "Unexpected first line! (length %d)\n", cols); return -1; } ++rows; while (1) { // Resize forest for next line. // Do the dumb thing and rely on realloc() to overallocate and manage // exponential growth of the underlying buffer // // If we were expecting huge input, we could just ask for a filename and // mmap() it. char * p = realloc(forest, (long) cols * (rows + 1) + 1); if (!p) { fprintf(stderr, "Realloc %ld fail! (%s)\n", (long) cols * (rows + 1) + 2, strerror(errno)); free(forest); return -1; } forest = p; // Read line. p = forest + cols * rows; if (!fgets(p, cols + 1, stdin)) break; // Check line length if (strlen(p) != cols || p[cols - 1] != '\n') { fprintf(stderr, "Unexpected line length for %s\n", p); free(forest); return -1; } ++rows; } printf("Trees seen: %d\n", forest_seen((unsigned char *) forest, rows, cols)); free(forest); return 0; }