Day 16 — Question Guys, what do you think is there a way to find the best point to start the beam by analyzing a layout? or just bruteforce for rescue? Haven’t seen other’s solutions yet.
@zelark If you enter at one loc, and then look at all the places where the beam exits, all those exit points and the original entry point would all be a related group, and all get the same score no matter which one you chose as the entry? Is that right? If that logic works, then you could skip the entire group.
I don't think that's right. The splitter blocks (`-` and |) don't behave the same in reverse. If I've understood the idea correctly, we'd like to say that if the beam enters at A and exits at B then the beam could enter at B and exit at A, meaning those points are in the same group and would get the same score. But I don't think that's the case.
Yeah, I think you are right @cdpjenkins, the splitter blocks mess up that idea.
It's a shame because it would have massively reduced the search space!
On second thought… I think it does work. If you have a setup like this:
.....
.....
..|..
.....
.....
And you come from the left side in the middle, you’ll end up with this:
..^..
..^..
>>|..
..v..
..v..
If you instead try from either the top or the bottom (which are now known exits) you’ll still get one of these
..v.. ..^..
..v.. ..^..
..|.. ..|..
..v.. ..^..
..v.. ..^..
…both of which have fewer energized cells. So we don’t need to bother trying a search from either of these known exits.
I implemented this and it worked (gave the right answer) but it didn’t reduce the time to run.For me excluding known exits led to reducing execution time by 1/3 (both solutions running in ~2 sec. in my machine after the cut).
Many thanks. I just added a set of known exit nodes which are then filtered out... it shaved 200ms off my execution time. (Sadly my part 2 still takes 581 ms... I wish I could reduce this further!)
Nice, I need to study your solution when I have time. I confess I did try something like this but my idea was quite unsophisticated and I just tried to memoise everything (which blew up my JVM heap because there are too many states).
Day 16 - Solutions
@michaeljweaver Hehe, my part 2 takes ~2 minutes even with pmap . I know how it could be optimized, but too lazy to do that. Maybe later ^_^
Here’s mine 11 seconds for part 2 https://github.com/bhauman/adv2023/blob/main/src/adv2023/day16/sol.clj
https://github.com/rjray/advent-2023-clojure/blob/master/src/advent_of_code/day16.clj
Mine. 28s on my desktop for part 2, but I don't run it compiled, I just run with lein run.
First try: 1.6 seconds on my M1 - I did not attempt to optimize but something could probably be done with transient collections or similar.
I went with a breath-first-traversal using a queue in a loop.
My https://github.com/wevre/advent-of-code/blob/master/src/advent_of_code/2023/day_16_mirrors.clj. It’s not optimized. Part 2 takes almost 8 seconds to run, but I’m not too bothered by that.
solution: https://github.com/erdos/advent-of-code/blob/master/2023/day16.clj
it is just a flood fill. I was playing with multimethods to dispatch on the cell type but the embedded case expressions were shorter at the end.
I haven't been posting my solutions this year, but they're all in my https://github.com/abyala/advent-2023-clojure. https://github.com/abyala/advent-2023-clojure/blob/main/src/advent_2023_clojure/day16.clj, as well as my https://github.com/abyala/advent-2023-clojure/blob/main/docs/day16.md (for non-Clojurians).
My take https://github.com/gveres/advent-of-code-2023-clojure/blob/main/src/day16.clj Very simulation-ish as opposed to "think about a good algorithm", has a lot of conds... would like to clean it up, but gets the job done. 3.4 seconds on an M1 Pro Mac.
Figured out how it could be optimized. We can detect a beam loop. Once it’s detected, we eliminate the beam. Finally, once the all beams eliminated we can count energized tiles ⚡. It makes my solution 10-15 times faster. So part 1 takes only 41 msecs, and part 2 takes 1353 msecs ☺️ https://github.com/zelark/AoC/blob/master/src/zelark/aoc_2023/day_16.clj
That's kind of what I'm also doing: keep a log of all [position incoming-direction] tuples, and if one comes up again, I drop that ray from my active rays set. I actually do an infinite lazy seq, and just drop-while until I have any rays. By the time all rays are gone (either left the grid or went into a loop), we're done. BUT, mine is still half as fast, so I'll need to look again facepalm.
And mine finally, 1.5s for part-2 (with pmap) https://github.com/genmeblog/advent-of-code/blob/master/src/advent_of_code_2023/day16.clj