120 lines
2.8 KiB
C
120 lines
2.8 KiB
C
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <omp.h>
|
|
|
|
#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);
|
|
}
|