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());
}