#include #include #include #define COUNT(a) ((int)(sizeof(a) / sizeof 0 [a])) #define FORLINE \ char *line = NULL; \ size_t len = 0; \ while (getline(&line, &len, fp) != EOF) #define FREELINE \ if (line) \ free(line) enum segments { SEG0 = 6, SEG1 = 2, SEG2 = 5, SEG3 = 5, SEG4 = 4, SEG5 = 5, SEG6 = 6, SEG7 = 3, SEG8 = 7, SEG9 = 6, }; #define SEG(x) (SEG##x) #define UNIQSEG(x) (x == SEG1 ? 1 : x == SEG4 ? 4 : x == SEG7 ? 7 : x == SEG8 ? 8 : 0) static int part_one(FILE *fp) { int res = 0; FORLINE { char *p = line; while (*p != '|') p++; p += 2; // space after | for (int i = 0; i < 4; i++) { int size = 0; while (*p != ' ' && *p != '\n') { size++; p++; } p++; // Space after end if (UNIQSEG(size)) res++; } } FREELINE; return res; } // Longest function ever INCOMING!! static int part_two(FILE *fp) { int res = 0; FORLINE { char *p = line; // Parse input struct input { char seq[8]; int len; int num; }; struct input input[10] = { 0 }; for (int i = 0; i < COUNT(input); i++) { sscanf(p, "%[^ ] %n", input[i].seq, &input[i].len); p += input[i].len; input[i].len--; input[i].num = -1; } while (*p != '|') p++; p += 2; // Space after | // Solve input struct input *found[10] = { 0 }; int count = 0; // First look for unique segments for (int i = 0; i < COUNT(input); i++) { int uniq = UNIQSEG(input[i].len); if (uniq) { //printf("found %d: %s\n", uniq, input[i].seq); found[uniq] = &input[i]; input[i].num = uniq; count++; } } // Now the others based on the uniques int i = 0; while (count < COUNT(input)) { if (++i == COUNT(input)) i = 0; if (input[i].num >= 0) continue; if (input[i].len == 6) { if (!found[6]) { int valid = 0; for (int j = 0; j < input[i].len; j++) for (int k = 0; k < found[1]->len; k++) if (input[i].seq[j] != found[1]->seq[k]) valid++; else valid--; if (valid == 10) { //printf("found 6: %s\n", input[i].seq); found[6] = &input[i]; input[i].num = 6; count++; continue; } } if (!found[9]) { int valid = 0; for (int j = 0; j < input[i].len; j++) { for (int k = 0; k < found[4]->len; k++) { if (input[i].seq[j] == found[4]->seq[k]) { valid++; break; } } if (valid == found[4]->len) { //printf("found 9: %s\n", input[i].seq); found[9] = &input[i]; input[i].num = 9; count++; valid = -1; break; } } if (valid < 0) continue; } // You only need to solve 2/3 if (found[6] && found[9]) { //printf("found 0: %s\n", input[i].seq); found[0] = &input[i]; input[i].num = 0; count++; } } else if (input[i].len == 5) { if (!found[3]) { int valid = 0; for (int j = 0; j < input[i].len; j++) { for (int k = 0; k < found[1]->len; k++) { if (input[i].seq[j] == found[1]->seq[k]) { valid++; break; } } if (valid == found[1]->len) { //printf("found 3: %s\n", input[i].seq); found[3] = &input[i]; input[i].num = 3; count++; valid = -1; break; } } if (valid < 0) continue; } // 5 is basically 6 if (!found[5] && found[6]) { int valid = 0; for (int j = 0; j < input[i].len; j++) { for (int k = 0; k < found[6]->len; k++) { if (input[i].seq[j] == found[6]->seq[k]) { valid++; break; } } if (valid == found[6]->len - 1) { //printf("found 5: %s\n", input[i].seq); found[5] = &input[i]; input[i].num = 5; count++; valid = -1; break; } } if (valid < 0) continue; } // You only need to solve 2/3 if (found[5] && found[6]) { //printf("found 2: %s\n", input[i].seq); found[2] = &input[i]; input[i].num = 2; count++; } } else { fprintf(stderr, "Huh: %d\n", input[i].len); } } // Parse output struct output { char seq[8]; int len; }; struct output output[4] = { 0 }; for (i = 0; i < COUNT(output); i++) { sscanf(p, "%[^ ] %n", output[i].seq, &output[i].len); p += output[i].len; output[i].len--; for (int j = 0; j < COUNT(found); j++) { int valid = 0; if (output[i].len == found[j]->len) { for (int k = 0; k < output[i].len; k++) { for (int l = 0; l < found[j]->len; l++) { if (output[i].seq[k] == found[j]->seq[l]) valid++; } } if (valid == output[i].len) { res += j * (i == 3 ? 1 : i == 2 ? 10 : i == 1 ? 100 : i == 0 ? 1000 : 0); continue; } } } } } FREELINE; return res; } int main(int argc, char *argv[]) { (void)argc; (void)argv; FILE *fp = fopen("input", "r"); if (!fp) exit(EXIT_FAILURE); clock_t tic = clock(); printf("%d\n", part_one(fp)); rewind(fp); printf("%d\n", part_two(fp)); clock_t toc = clock(); printf("TIME: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC); fclose(fp); return 0; }