Day 7: Laboratories ## 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

  • janAkali
    link
    fedilink
    arrow-up
    3
    ·
    8 months ago

    Nim

    Another simple one.

    Part 1: count each time a beam crosses a splitter.
    Part 2: keep count of how many particles are in each column in all universes
    (e.g. with a simple 1d array), then sum.

    Runtime: 116 μs 95 µs 86 µs

    old version
    type
      AOCSolution[T,U] = tuple[part1: T, part2: U]
    
    proc solve(input: string): AOCSolution[int, int] =
      var beams = newSeq[int](input.find '\n')
      beams[input.find 'S'] = 1
    
      for line in input.splitLines():
        var newBeams = newSeq[int](beams.len)
        for pos, cnt in beams:
          if cnt == 0: continue
          if line[pos] == '^':
            newBeams[pos-1] += cnt
            newBeams[pos+1] += cnt
            inc result.part1
          else:
            newbeams[pos] += cnt
        beams = newBeams
      result.part2 = beams.sum()
    

    Update: found even smaller and faster version that only needs a single array.
    Update #2: small optimization

    type
      AOCSolution[T,U] = tuple[part1: T, part2: U]
    
    proc solve(input: string): AOCSolution[int, int] =
      var beams = newSeq[int](input.find '\n')
      beams[input.find 'S'] = 1
    
      for line in input.splitLines():
        for pos, c in line:
          if c == '^' and beams[pos] > 0:
            inc result.part1
            beams[pos-1] += beams[pos]
            beams[pos+1] += beams[pos]
            beams[pos] = 0
      result.part2 = beams.sum()
    

    Full solution at Codeberg: solution.nim

  • strlcpy
    link
    fedilink
    English
    arrow-up
    2
    ·
    8 months ago

    C

    Accidentally solved part 2 first but had the foresight to save the code. Otherwise my solution looks similar to what other people are doing, just with more code 😅

    Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <inttypes.h>
    #include <assert.h>
    
    #define GW 148
    #define GH 74
    
    static char g[GH][GW];
    static uint64_t dp[2][GW];
    static int w,h;
    
    /* recursively traces beam for part 1, marking visited splitters with 'X' */
    static uint64_t
    solve_p1(int x, int y)
    {
    	if (x<0 || x>=w || y<0 || y>=h || g[y][x] == 'X')
    		return 0;
    	else if (g[y][x] != '^')
    		return solve_p1(x, y+1);
    	else {
    		g[y][x] = 'X';
    		return 1 + solve_p1(x-1, y) + solve_p1(x+1, y);
    	}
    }
    
    /* DP for part 2 */
    static uint64_t
    solve_p2(void)
    {
    	int x,y, odd;
    
    	for (y=h-1; y>=0; y--)
    	for (x=1; x<w-1; x++) {
    		/* only two rows relevant at a time, so don't store any more */
    		odd = y&1;
    
    		if (g[y][x] == 'S') {
    			printf("\n");
    			return dp[!odd][x] + 1;
    		}
    
    		dp[odd][x] = g[y][x] == '^' || g[y][x] == 'X'
    		    ? dp[!odd][x-1] + dp[!odd][x+1] + 1
    		    : dp[!odd][x];
    	}
    
    	return 0;
    }
    
    int
    main()
    {
    	int x,y, sx,sy;
    
    	for (h=0; ; ) {
    		/* one bottom row of padding */
    		assert(h < GH-1);
    		/* input already side padded, plus we have \n\0 */
    		if (!fgets(g[h], GW, stdin))
    			break;
    		/* skip empty rows */
    		for (x=0; g[h][x]; x++)
    			if (g[h][x] == 'S' || g[h][x] == '^')
    				{ h++; break; }
    	}
    
    	w = strlen(g[0])-1; /* strip \n */
    
    	for (y=0; y<h; y++)
    	for (x=0; x<w; x++)
    		if (g[y][x] == 'S')
    			{ sx=x; sy=y; break; }
    
    	printf("07: %"PRIu64" %"PRIu64"\n", solve_p1(sx,sy), solve_p2());
    }
    
  • strlcpy
    link
    fedilink
    English
    arrow-up
    1
    ·
    8 months ago

    Ahh I knew there would be some simple combined representation like this but couldn’t be bothered. Nice!