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

  • sjmulder@lemmy.sdf.org
    link
    fedilink
    arrow-up
    2
    ·
    edit-2
    3 days ago

    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