Day 23: LAN Party
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
C
Graph problems are not my cake but this one I could work out: recursively iterate unique combination of adjacent nodes. Performance benefits from using a basic, int-indexed adjacency matrix.
Fast enough on my 2015 PC:
day23 0:00.05 1644 Kb 0+143 faults
Code
#include "common.h" #define VZ 520 /* max no. vertices */ #define SZ 32 /* max set size */ static char names[VZ][3]; static char adj[VZ][VZ]; static int nvert; static int to_id(const char *name) { int i; for (i=0; i<nvert; i++) if (!strcmp(name, names[i])) return i; assert(nvert < VZ); assert(strlen(name) < LEN(*names)); snprintf(names[nvert++], sizeof(*names), "%s", name); return i; } static int cmp_id(const void *a, const void *b) { return strcmp(names[*(int*)a], names[*(int*)b]); } /* * Construct all unique combinations of nodes, with every extension, * confirm they're all connected. Essentally this but recursive: * * for (a=0; a<nvert; a++) * for (b=a+1; b<nvert; b++) * for (c=b+1; c<nvert; c++) * ... * * Note the inner loops continue forward from the point of the outside * loop, avoiding duplicate combinations. * * 'set' and 'best' are arrays of size SZ, length 'sz' and 'bz'. 'set' * is the current working state; 'best' is a copy of the longest known * set. */ static int max_set(int *set, int sz, int *best, int bz) { int bz1, v,i; assert(sz < SZ); /* for each potential candidate */ for (v = sz ? set[sz-1]+1 : 0; v < nvert; v++) { /* adjacent to all in current set? */ for (i=0; i<sz && adj[set[i]][v]; i++) ; if (i != sz) continue; /* recur and update 'best size' if needed */ set[sz] = v; if (bz < (bz1 = max_set(set, sz+1, best, bz))) bz = bz1; } /* store longest known set in 'best' */ if (sz > bz) memcpy(best, set, (bz = sz) * sizeof(*best)); return bz; } int main(int argc, char **argv) { static int set[SZ], best[SZ]; char buf[8]; int p1=0, a,b,c, i, bz; if (argc > 1) DISCARD(freopen(argv[1], "r", stdin)); while (fgets(buf, sizeof(buf), stdin)) { assert(strlen(buf) >= 5); buf[2] = buf[5] = '\0'; a = to_id(buf); b = to_id(buf+3); adj[a][b] = adj[b][a] = 1; } for (a=0; a<nvert; a++) for (b=a+1; b<nvert; b++) for (c=b+1; c<nvert; c++) p1 += adj[a][b] && adj[a][c] && adj[b][c] && ( names[a][0] == 't' || names[b][0] == 't' || names[c][0] == 't'); printf("23: %d ", p1); bz = max_set(set, 0, best, 0); qsort(best, bz, sizeof(*best), cmp_id); for (i=0; i<bz; i++) printf(i ? ",%s" : "%s", names[best[i]]); putchar('\n'); return 0; }
https://codeberg.org/sjmulder/aoc/src/branch/master/2024/c/day23.c