Day23
This commit is contained in:
199
day23/c/day23.c
Normal file
199
day23/c/day23.c
Normal file
@@ -0,0 +1,199 @@
|
||||
#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);
|
||||
}
|
||||
Reference in New Issue
Block a user