200 lines
5.5 KiB
C
200 lines
5.5 KiB
C
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#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);
|
|
}
|