• 3 Posts
  • 57 Comments
Joined 1 year ago
cake
Cake day: June 12th, 2023

help-circle











  • C

    Fun and interesting puzzle! In part 1 I fumbled a bit trying to implement even/odd outside/inside tracking before realizing that wouldn’t work for this shape and just did the flood fill.

    For part 2 I correctly guessed that like the intersecting cuboids (2021 day 22) it would be about finding a better representation for the grid or avoiding representing it entirely. Long story shorter:

    /*
     * Conceptually: the raw map, which is too large to fit directly in
     * memory for part 2, is made much smaller by collapsing (and counting)
     * identical rows and columns. Another way to look it at is that a grid
     * is fitted to make 'opaque' cells.
     *                                           |   |#|##|#
     * For example:                             -+---+-+--+-
     *                                          #|###|#|  |#
     *       ####               ### 1           -+---+-+--+-
     *   #####  #             ### # 1           #|   | |  |#
     *   #      #   becomes   #   # 2     or:   #|   | |  |#
     *   #      #             ##### 1           -+---+-+--+-
     *   ########             13121             #|###|#|##|#
     *
     * To avoid a lot of complex work, instead of actually collapsing and
     * splitting rows and columns, we first generate the wall rectangles and
     * collect the unique X and Y coordinates. Those are locations of our
     * virtual grid lines.
     */
    

    Despite being quite happy with this solution, I couldn’t help but notice the brevity and simplicity of the other solutions here. Gonna have a look what’s happening there and see if I can try that approach too.

    (Got bitten by a nasty overflow btw, the list of unique X coordinates was overwriting the list of unique Y coordinates. Oh well, such is the life of a C programmer.)

    https://github.com/sjmulder/aoc/blob/master/2023/c/day18.c



  • C

    Just tracing the ray. When it splits, recurse one way and continue the other. Didn’t bother with a direction lookup table this time, just a few ifs. The ray ends when it goes out of bounds or a ray in that direction has been previously traced on a given cell (this is tracked with a separate table).

    It would’ve been straightforward if I hadn’t gotten the ‘previously visited’ check wrong 😞. I was checking against the direction coming in of the tile but marking the direction going out.

    Ray function:

    static void
    ray(int x, int y, int dir)
    {
    	int c;
    
    	while (x>=0 && y>=0 && x<w && y<h) {
    		if (beams[y][x] & (1 << dir))
    			break;
    
    		beams[y][x] |= 1 << dir;
    		c = map[y][x];
    
    		if (dir==NN && c=='/')  dir = EE; else
    		if (dir==EE && c=='/')  dir = NN; else
    		if (dir==SS && c=='/')  dir = WW; else
    		if (dir==WW && c=='/')  dir = SS; else
    		if (dir==NN && c=='\\') dir = WW; else
    		if (dir==EE && c=='\\') dir = SS; else
    		if (dir==SS && c=='\\') dir = EE; else
    		if (dir==WW && c=='\\') dir = NN; else
    		if (dir==NN && c=='-') { ray(x,y,WW); dir = EE; } else
    		if (dir==SS && c=='-') { ray(x,y,WW); dir = EE; } else
    		if (dir==EE && c=='|') { ray(x,y,NN); dir = SS; } else
    		if (dir==WW && c=='|') { ray(x,y,NN); dir = SS; } 
    
    		x += dir==EE ? 1 : dir==WW ? -1 : 0;
    		y += dir==SS ? 1 : dir==NN ? -1 : 0;
    	}
    }
    

    https://github.com/sjmulder/aoc/blob/master/2023/c/day16.c-





  • C

    Chose not to do transposing/flipping or fancy indexing so it’s rather verbose, but it’s also clear and (I think) fast. I also tried to limit the number of search steps by keeping two cursors in the current row/col, rather than shooting a ray every time.

    Part 2 immediately reminded me of that Tetris puzzle from day 22 last year so I knew how to find and apply the solution. State hashes are stored in an array and (inefficiently) scanned until a loop is found.

    One direction of the shift function:

    /*
     * Walk two cursors i and j through each column x. The i cursor
     * looks for the first . where an O can go. The j cursor looks
     * ahead for O's. When j finds a # we start again beyond it.
     */
    for (x=0; x