#include #include #include #include #define CHARS_MAX 6 #define MAX_KEYS 1024 #define MAX_LOCKS 1024 typedef enum { EMPTY, FILLED } tile_t; typedef struct pattern { tile_t schematic[7][5]; uint8_t list[5]; } pattern_t; int main() { char c; pattern_t *locks = calloc(MAX_LOCKS, sizeof(locks[0])); pattern_t *keys = calloc(MAX_KEYS, sizeof(keys[0])); int lock_count = 0, key_count = 0; int *count; int i = 0, j = 0; int reading_lock = 0, reading_key = 0; while ((c = getchar()) != EOF) { if (c == '\n') { i = 0; if (reading_lock == 0 && reading_key == 0) { continue; } if (j == 6) { j = 0; reading_lock = 0; reading_key = 0; (*count)++; } else { j++; } continue; } if (!reading_lock && !reading_key) { switch (c) { case '.': reading_key = 1; break; case '#': reading_lock = 1; break; } } pattern_t *pattern_collector = reading_lock ? locks : keys; count = reading_lock ? &lock_count : &key_count; switch (c) { case '.': pattern_collector[*count].schematic[j][i] = EMPTY; break; case '#': pattern_collector[*count].schematic[j][i] = FILLED; break; } i++; } // Parse each lock schematic into list of numbers for (int i = 0; i < lock_count; i++) { for (int j = 0; j < 5; j++) { uint8_t value = 0; for (int k = 1; k < 7; k++) { value += locks[i].schematic[k][j] == FILLED; } locks[i].list[j] = value; } } // Parse each key schematic into list of numbers for (int i = 0; i < key_count; i++) { for (int j = 0; j < 5; j++) { uint8_t value = 0; for (int k = 5; k >= 0; k--) { value += keys[i].schematic[k][j] == FILLED; } keys[i].list[j] = value; } } uint64_t good = 0; // Every key with every lock #pragma omp parallel for for (int i = 0; i < lock_count; i++) { for (int j = 0; j < key_count; j++) { int potential = 1; for (int k = 0; k < 5; k++) { if (locks[i].list[k] + keys[j].list[k] > 5) { potential = 0; break; } } if (potential) #pragma omp critical { good++; } } } printf("%lu\n", good); free(locks); free(keys); }