puzzle.c (2969B)
1 #define _DEFAULT_SOURCE 2 3 #include <limits.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <errno.h> 7 #include <string.h> 8 #include <strings.h> 9 #include <assert.h> 10 #include <stdbool.h> 11 12 #define STR_LEN 2048 13 // 140x140 for real one 14 //#define FIELD_SIZE 10 15 #define FIELD_SIZE 140 16 17 bool is_digit(char b) { 18 return b>='0' && b<='9'; 19 } 20 21 typedef struct Gear { 22 int pos; // y * FIELD_SIZE + x 23 int part; 24 struct Gear *next; 25 } Gear; 26 27 Gear * find_gear(Gear *gears, int pos) { 28 Gear *gear = gears; 29 while (gear != NULL) { 30 if (gear->pos == pos) { 31 return gear; 32 } 33 gear = gear->next; 34 } 35 return NULL; 36 } 37 38 Gear * make_gear(Gear *prev) { 39 Gear *gear = malloc(sizeof(Gear)); 40 memset(gear, 0, sizeof(Gear)); 41 if (prev!=NULL) { 42 prev->next = gear; 43 } 44 return gear; 45 } 46 47 bool check_part(int x, int y, const char (*field)[FIELD_SIZE][FIELD_SIZE]) { 48 for (int dy=-1; dy<=1; ++dy) { 49 for (int dx=-1; dx<=1; ++dx) { 50 int dy1=y+dy; 51 int dx1=x+dx; 52 if (dy1>=0 && dy1<FIELD_SIZE && dx1>=0 && dx1<FIELD_SIZE) { 53 if (!is_digit((*field)[dy1][dx1]) && (*field)[dy1][dx1]!='.') { 54 return true; 55 } 56 } 57 } 58 } 59 return false; 60 } 61 62 int check_gear(int x, int y, const char (*field)[FIELD_SIZE][FIELD_SIZE]) { 63 for (int dy=-1; dy<=1; ++dy) { 64 for (int dx=-1; dx<=1; ++dx) { 65 int dy1=y+dy; 66 int dx1=x+dx; 67 if (dy1>=0 && dy1<FIELD_SIZE && dx1>=0 && dx1<FIELD_SIZE) { 68 if ((*field)[dy1][dx1]=='*') { 69 return dy1*FIELD_SIZE+dx1; 70 } 71 } 72 } 73 } 74 return -1; 75 } 76 77 void puzzle(const char *filename, long long *result1, long long *result2) { 78 FILE *infile = fopen(filename, "r"); 79 if (infile == NULL) { 80 fprintf(stderr, "fopen() error: %s\n", strerror(errno)); 81 return; 82 } 83 84 char field[FIELD_SIZE][FIELD_SIZE] = {0}; 85 char buf[STR_LEN] = {0}; 86 unsigned int line_num = 0; 87 88 *result1 = 0; 89 *result2 = 0; 90 91 while (fgets(buf, STR_LEN, infile) != NULL) { 92 for (int i=0; i<FIELD_SIZE; ++i) { 93 field[line_num][i] = buf[i]; 94 } 95 ++line_num; 96 bzero(buf, STR_LEN); 97 } 98 99 // mutiny! ignoring feof/ferror. 100 fclose(infile); 101 102 Gear *gears = NULL; 103 Gear *gear_last = NULL; 104 105 for (int y=0; y<FIELD_SIZE; ++y) { 106 int x = 0; 107 while (x<FIELD_SIZE) { 108 int digit = 0; 109 bool is_part = false; 110 int gear_pos = -1; 111 while (is_digit(field[y][x++])) { 112 int cx = x-1; 113 if (cx>=FIELD_SIZE) break; // too lazy to make it sane 114 if (check_part(cx, y, &field)) is_part = true; 115 digit = digit*10 + field[y][cx] - '0'; 116 if (gear_pos==-1) gear_pos = check_gear(cx, y, &field); 117 } 118 if (digit>0 && is_part) { 119 //printf("%d\n", digit); 120 *result1 += digit; 121 122 if (gear_pos != -1) { 123 Gear *gear = find_gear(gears, gear_pos); 124 if (gear!=NULL) { 125 *result2 += digit * gear->part; 126 gear->part = digit; 127 } else { 128 gear = make_gear(gear_last); 129 gear->pos = gear_pos; 130 gear->part = digit; 131 if (gears==NULL) gears = gear; 132 133 if (gear_last!=NULL) { 134 gear_last->next = gear; 135 } 136 gear_last = gear; 137 } 138 } 139 } 140 } 141 } 142 }