Haskell
That was a fun little problem.
import Data.Map qualified as Map
import Data.Set qualified as Set
import Data.Tuple (swap)
readInput s =
Map.fromDistinctAscList
[((i, j), c) | (i, l) <- zip [0 ..] $ lines s, (j, c) <- zip [0 ..] l]
beamPaths input = scanl step (Map.singleton startX 1) [startY .. endY]
where
Just (startY, startX) = lookup 'S' $ map swap $ Map.assocs input
Just ((endY, _), _) = Map.lookupMax input
step beams y =
Map.unionsWith (+) $
[ if input Map.!? (y + 1, j) == Just '^'
then Map.fromList [(j - 1, n), (j + 1, n)]
else Map.singleton j n
| (j, n) <- Map.assocs beams
]
part1 = sum . map Set.size . (zipWith (Set.\\) <*> tail) . map Map.keysSet . beamPaths
part2 = sum . last . beamPaths
main = do
input <- readInput <$> readFile "input07"
print $ part1 input
print $ part2 input