uppgb.c (2096B)
1 #include "common.h" 2 3 static inline size_t parse_next(uint64_t **rows, size_t *nrows, uint64_t **cols, 4 size_t *ncols, char **lines, size_t nlines, 5 size_t s) { 6 size_t i, j; 7 size_t nc = strlen(lines[s]) - 1; 8 9 // find number of rows 10 size_t nr = 0; 11 while (s + nr < nlines && 12 (lines[s + nr][0] == '.' || lines[s + nr][0] == '#')) { 13 nr++; 14 } 15 16 // read rows 17 uint64_t *r = malloc(nr * sizeof(*r)); 18 for (i = 0; i < nr; i++) { 19 // read row i 20 r[i] = 0; 21 for (j = 0; j < nc; j++) { 22 r[i] <<= 1; 23 if (lines[s + i][j] == '#') { 24 r[i] += 1; 25 } 26 } 27 } 28 29 // read cols 30 uint64_t *c = malloc(nc * sizeof(*r)); 31 for (i = 0; i < nc; i++) { 32 c[i] = 0; 33 for (j = 0; j < nr; j++) { 34 c[i] <<= 1; 35 if (lines[s + j][i] == '#') { 36 c[i] += 1; 37 } 38 } 39 } 40 41 // output 42 *rows = r; 43 *cols = c; 44 *nrows = nr; 45 *ncols = nc; 46 47 return nr + 1; 48 } 49 50 /** 51 * Checks if n is a _positive_ power of 2. 52 */ 53 static inline int is_power2(const uint64_t n) { 54 uint64_t t; 55 56 __asm__ volatile("POPCNT %1, %0;" : "=r"(t) : "r"(n) :); 57 58 return t == 1; 59 } 60 61 static inline int is_refl(uint64_t *v, size_t nv, int i) { 62 int j = i + 1; 63 64 size_t smuts = 0; 65 while (0 <= i && j < (int)nv) { 66 if (v[i] != v[j]) { 67 if (!is_power2(v[i] ^ v[j])) 68 return 0; 69 if (smuts > 0) 70 return 0; 71 72 smuts++; 73 } 74 75 i--; 76 j++; 77 } 78 79 if (smuts == 0) 80 return 0; 81 82 return 1; 83 } 84 85 int main(int argc, char **argv) { 86 char **lines; 87 size_t i; 88 size_t nlines = readlines(&lines, "input"); 89 90 size_t cr = 0; 91 uint64_t summa = 0; 92 uint64_t *rows, *cols; 93 size_t nrows, ncols; 94 while (cr < nlines) { 95 cr += parse_next(&rows, &nrows, &cols, &ncols, lines, nlines, cr); 96 97 for (i = 0; i < nrows - 1; i++) { 98 if (is_refl(rows, nrows, (int)i)) 99 summa += 100 * (i + 1); 100 } 101 102 for (i = 0; i < ncols - 1; i++) { 103 if (is_refl(cols, ncols, (int)i)) 104 summa += (i + 1); 105 } 106 107 free(rows); 108 free(cols); 109 } 110 111 printf("%llu\n", summa); 112 }