#include #include #include #include #define CHARS_MAX 6 #define MAX_LINKS 16*1024 #define MAX_NODES 8*1024 typedef struct link { char left[2]; char right[2]; } link_t; int cmp(const void* a, const void* b) { const char (*pa)[2] = a; const char (*pb)[2] = b; if ((*pa)[0] != (*pb)[0]) { return (*pa)[0] - (*pb)[0]; } return (*pa)[1] - (*pb)[1]; } int main() { char *p, *buf, c; buf = calloc(CHARS_MAX, sizeof(char)); p = buf; link_t *links = calloc(MAX_LINKS, sizeof(link_t)); int link_count = 0; while ((c = getchar()) != EOF) { *p++ = c; if (c != '\n') { continue; } links[link_count].left[0] = buf[0]; links[link_count].left[1] = buf[1]; links[link_count].right[0] = buf[3]; links[link_count].right[1] = buf[4]; link_count++; memset(buf, 0, CHARS_MAX); p = buf; } free(buf); // Find unique nodes char (*nodes)[2] = calloc(MAX_NODES, sizeof(nodes[0])); int node_count = 0; for (int i = 0; i < link_count; i++) { // Add left int found = 0; for (int j = 0; j < node_count; j++) { if (!memcmp(nodes[j], links[i].left, sizeof(nodes[0]))) { found = 1; break; } } if (!found) { memcpy(nodes[node_count++], links[i].left, sizeof(nodes[0])); } // Right found = 0; for (int j = 0; j < node_count; j++) { if (!memcmp(nodes[j], links[i].right, sizeof(nodes[0]))) { found = 1; break; } } if (!found) { memcpy(nodes[node_count++], links[i].right, sizeof(nodes[0])); } } // Create adjacency matrix uint8_t **adjacency = calloc(node_count, sizeof(adjacency[0])); for (int i = 0; i < node_count; i++) { adjacency[i] = calloc(node_count, sizeof(adjacency[0][0])); } for (int i = 0; i < node_count; i++) { for (int j = 0; j < node_count; j++) { if (i == j) { adjacency[i][j] = 1; } // Check if there's a link from i to j for (int k = 0; k < link_count; k++) { if (!memcmp(links[k].left, nodes[i], sizeof(nodes[0])) && !memcmp(links[k].right, nodes[j], sizeof(nodes[0]))) { adjacency[i][j] = 1; break; } if (!memcmp(links[k].right, nodes[i], sizeof(nodes[0])) && !memcmp(links[k].left, nodes[j], sizeof(nodes[0]))) { adjacency[i][j] = 1; break; } } } } free(links); uint64_t groups = 0; // Check each node that starts with 't' for (int i = 0; i < node_count; i++) { for (int j = i; j < node_count; j++) { if (i == j || adjacency[i][j] == 0) { continue; } // We have a link from i to j // Check if there's a k in j's neighbors that has a link to i for (int k = j; k < node_count; k++) { if (k == j || k == i || adjacency[j][k] == 0 || adjacency[k][i] == 0) { continue; } // At least one 't' if (nodes[i][0] != 't' && nodes[j][0] != 't' && nodes[k][0] != 't') { continue; } groups++; } } } printf("%lu\n", groups); uint64_t largest_conn_count = 0; for (int i = 0; i < node_count; i++) { uint64_t connections = 0; for (int j = 0; j < node_count; j++) { if (adjacency[i][j] == 1) { connections++; } } if (connections > largest_conn_count) { largest_conn_count = connections; } } for (int i = 0; i < node_count; i++) { // Get connected node idxs int *connected = calloc(largest_conn_count, sizeof(connected[0])); int count = 0; for (int j = 0; j < node_count; j++) { if (adjacency[i][j]) { connected[count++] = j; } } // Check whether everyone is connected with everyone int good = 1; for (int l = 0; l < count; l++) { for (int j = 0; j < count; j++) { for (int k = 0; k < count; k++) { if (adjacency[connected[j]][connected[k]] == 0 && l != j && l != k) { good = 0; break; } } if (!good) { break; } } if (good) { char (*formatted)[2] = calloc(count - 1, sizeof(formatted[0])); int formatted_count = 0; for (int j = 0; j < count; j++) { if (j != l) { memcpy(formatted[formatted_count++], nodes[connected[j]], sizeof(nodes[0])); } } qsort(formatted, count - 1, sizeof(char[2]), cmp); for (int j = 0; j < count - 1; j++) { printf("%c%c", formatted[j][0], formatted[j][1]); if (j != count - 2) { printf(","); } } printf("\n"); } } free(connected); } for (int i = 0; i < node_count; i++) { free(adjacency[i]); } free(adjacency); free(nodes); }