puzzle.c (2608B)
1 #define _DEFAULT_SOURCE 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <errno.h> 6 #include <string.h> 7 #include <strings.h> 8 #include <assert.h> 9 #include <ctype.h> 10 #include <limits.h> 11 12 #define STR_LEN 1024 13 #define GRID_WIDTH 10 14 #define GRID_HEIGHT 10 15 #define STEPS 100 16 17 typedef int octopuses_t[GRID_HEIGHT][GRID_WIDTH]; 18 19 void step(octopuses_t *octopuses); 20 void print(octopuses_t *octopuses); 21 void light(octopuses_t *octopuses, int x, int y); 22 void process(octopuses_t *octopuses, int x, int y); 23 int normalize(octopuses_t *octopuses); 24 25 void puzzle(const char *filename, long long *result1, long long *result2) { 26 FILE *infile = fopen(filename, "r"); 27 if (infile == NULL) { 28 fprintf(stderr, "fopen() error: %s\n", strerror(errno)); 29 return; 30 } 31 32 char buf[STR_LEN] = {0}; 33 unsigned int line_num = 0; 34 octopuses_t octopuses = {0}; 35 36 *result1 = 0; 37 *result2 = 0; 38 39 while (fgets(buf, STR_LEN, infile) != NULL) { 40 size_t len = strlen(buf); 41 assert(len >= GRID_WIDTH); 42 for (int i = 0; i < GRID_WIDTH; ++i) { 43 assert(isdigit((int)buf[i])); 44 octopuses[line_num][i] = buf[i] - '0'; 45 } 46 ++line_num; 47 bzero(buf, STR_LEN); 48 } 49 50 for (int s = 1; s < INT_MAX; ++s) { 51 step(&octopuses); 52 int flashes = normalize(&octopuses); 53 if (s <= STEPS) { 54 *result1 += flashes; 55 } 56 if (flashes == GRID_WIDTH*GRID_HEIGHT) { 57 *result2 = s; 58 } 59 if (*result1 > 0 && *result2 > 0) { 60 break; 61 } 62 } 63 64 // mutiny! ignoring feof/ferror. 65 fclose(infile); 66 } 67 68 void step(octopuses_t *octopuses) { 69 for (int y = 0; y < GRID_HEIGHT; ++y) { 70 for (int x = 0; x < GRID_WIDTH; ++x) { 71 process(octopuses, x, y); 72 } 73 } 74 } 75 76 void process(octopuses_t *octopuses, int x, int y) { 77 int o = ++(*octopuses)[y][x]; 78 if (o == 10) { 79 light(octopuses, x, y); 80 } 81 } 82 83 void light(octopuses_t *octopuses, int x, int y) { 84 if (y > 0) process(octopuses, x, y-1); 85 if (y < GRID_HEIGHT-1) process(octopuses, x, y+1); 86 if (x > 0) { 87 process(octopuses, x-1, y); 88 if (y > 0) process(octopuses, x-1, y-1); 89 if (y < GRID_HEIGHT-1) process(octopuses, x-1, y+1); 90 } 91 if (x < GRID_WIDTH-1) { 92 process(octopuses, x+1, y); 93 if (y > 0) process(octopuses, x+1, y-1); 94 if (y < GRID_HEIGHT-1) process(octopuses, x+1, y+1); 95 } 96 } 97 98 int normalize(octopuses_t *octopuses) { 99 int flashes = 0; 100 for (int y = 0; y < GRID_HEIGHT; ++y) { 101 for (int x = 0; x < GRID_WIDTH; ++x) { 102 if ((*octopuses)[y][x] > 9) { 103 (*octopuses)[y][x] = 0; 104 ++flashes; 105 } 106 } 107 } 108 return flashes; 109 } 110 111 void print(octopuses_t *octopuses) { 112 for (int y = 0; y < GRID_HEIGHT; ++y) { 113 for (int x = 0; x < GRID_WIDTH; ++x) { 114 printf("%2d", (*octopuses)[y][x]); 115 } 116 printf("\n"); 117 } 118 }