Took me a little while to understand the problem, but once I did, ivec2 came in clutch once again.
Would have had part 2 sooner if not for the "also all antennas are now antinodes" thing which I just missed. You win again, reading comprehension.
Okay, this optimization was easier than I thought it'd be.
I started by not building a new list every time I wanted to operate on the next value since that seemed like low-hanging fruit. That helped, but not as much as I expected (as is always the case with optimization, I feel).
Next I ran this under a profiler and it showed that string concatenation was the biggest offender, so I found a way to do that without involving strings (it's a bit convoluted, but optimizations tend to do that...) and that cleaned up most of the problem.
After that, getting the next element from the list was a (very minor) next-highest offender, so I cached that locally.
Finally, on a whim I decided that the tuple wasn't helping me anymore, so I removed it and was surprised to see another 100ms or so disappear. I guess constructing those is worse than I thought...gotta file that away for later. I'm a little surprised that it didn't show up in the profiler (or I didn't know how to read it, perhaps).
Part 2 gave me more trouble than it should have, mostly because I was initially turning and stepping at the same time which ended up being a big mistake.
This runs in a few seconds in Debug, but only a half a second in Release. I feel like it can be much faster, but I don't have any ideas on doing that just yet.
It took me a minute to figure out a good solution for part 2, but I'm pretty happy with the custom-sort-function implementation.
I also really like the LINQ one-liners for getting the actual totals. I feel like future-me is going to be mad and confused, but right now it feels fun!
This solution feels pretty bad. I think I shouldn't have used my ivec2 utilities and just checked the next spots for part 2. It would probably have been simpler given all the constraints. I'm also certain there's a smarter way to solve this than what I did, but...it works, so...?
Since we no longer include input files with the solution, per AoC guidelines, this will enable other users to use this application (after specifying their session token) without manually grabbing all the appropriate download files.