Files
adventofcode2024/day23/c/day23.c
dobiadi d85878bca2 Day23
2024-12-23 13:42:25 +01:00

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);
}