Advent of Code 2019 - Day 7

Note: This topic is to talk about Day 7 of the Advent of Code 2019 .

There is a private leaderboard for elixirforum members. You can join it by following this link and entering the following code:

39276-eeb74f9a

1 Like

Here’s my solution: https://gist.github.com/QuinnWilton/e6fe3506240bf3abc4ef66c2f820a7e0

4 Likes

Part 1 was real easy, even though I haven’t bothered to fix up my Intcode computer like some of ya’ll have.

Part 2 actually wasn’t difficult either (just have to save state), except that both of the examples did not halt for me. After a while, I gave up trying to fix them and just ran the actual input and it worked. (Update: I realized that I have only been saving the instruction pointer value and not the memory. I am going to fix that real quick, but why did that even work??)

Code here, but I’m guessing our solutions for these intcode computer problems are just going to diverge more and more over time.

2 Likes

Very nice, super clean. I did want to try processes + messages, which would have been the Elixir/Erlang way, but I am just not that comfortable with all that stuff yet.

3 Likes

Here is my solution.

In part 1, I spent a significant amount of the time to implement my permutations function to lazily generate all phases.

In part 2, I spent some time before I realized that it would have been much easier to run each of the amplifiers in their own Erlang process and rewrite input/output to use message passing. Oh, well! I didn’t do that refactoring, but made the machine suspend on an output operation and saving the IP to make it possible to resume it later when I had new input for it.

4 Likes

This was a fun challenge! My solution is completely sequential. I solved part 1 as a special case of part 2.

Nice! I also went for lazy permutation. Here’s my approach.

2 Likes

Here are my solutions (though I am currently refactoring them, they will probably change). I am using advent of code to specifically learn Elixir (started using it like 4 days ago), it’s great to have other solutions to compare against.

In part 1 I basically just ran the intcode interpreters serially, but if you look at my commit I had forgotten to allow the IO object to be modified by my input / output instructions and I had to go back and fix it (as well as changing the halt instruction to allow the IO state to be returned). I am trying to keep my intcode interpreter in a specific style where I add on top of it each day rather than make it a separate library.

In part 2 I finally took the opportunity to learn the Erlang/Elixir threading model (the whole reason I picked this language) by running the interpreters in parallel. It seemed like a natural way to solve the problem. The alternative of course being to rewrite the interpreter to allow the IO instructions to cause it to break out of interpreting which I considered. My code for this is a mess because I was learning it as I was writing it, but it was very enjoyable.

This is very ugly, and took me forever to get working.

I finished the puzzle with a serially version, as I did in day 5 and day 2, at first. But while writing the code I had strong feelings that this is the perfect scenario for Process to shine.

So I refactor it into a new version with spawn and Process. The Intcode program interpreter is now more real, with ability to run, block to io and communicate with other processes. Hopefuly it can be used in later puzzles.

I was not familiar with Process module before today. Most of the time I was using GenServer, Task, and Agent. So I’m very happy that I learned a lot from the handy documentations, again.

It was so fun. :stuck_out_tongue:

1 Like

Wow it was tough but quite entertaining! :laughing:

I wrote it the messaging way, spawning exactly 600 processes : 1 task for each of the 120 signal permutations, each task was itself running 5 processes (one per amplifier). Running part2 puzzle takes exactly 91ms on my laptop :sunglasses:

Here is my code: https://github.com/cblavier/advent/blob/master/lib/2019/day7/part2.ex

1 Like

Here’s mine: solution, vm. I’ve opted to put the vm into a process so I can interact with it moving forward. I don’t think this is necessarily a great design but it works and I’ve hit my hour time limit for today’s problem.

Just committed my day7 solution

I finished a couple of minutes ago.

Part1 was quite easy to solve and didn’t require any changes to the VM code itself.

For Part2 I hacked some send/receive mechanics into it, but its quite ugly and I will probably refactor the machine at some point in time to always run as a named process.

1 Like

A few hours later, just made another pass of refactoring on my code.

It’s much more easy to understand now (I think :sweat_smile:)

I rarely revise my AoC solutions after the fact, but today I did, to learn how to use processes and messages.

Unsurprisingly, it turned out to be a cleaner, albeit slightly more complex solution: fewer LoC and less data being slung around, but more moving parts -> more failure modes.

Somewhat surprisingly, it required very minimal changes to my existing interpreter code (the main reason I didn’t do it this way from the start).

Revised Day 7 Part 2

Catching up. I finally feel like my Intcode module is reaching a decent place.

Day 7 frustrated me a ton with the definition of the second problem. It was not very difficult to get it to work (I went with the approach where input/output are done through message passing and running the evaluators in parallel), but it was very challenging for me to figure out the execution model they wanted and where the output was supposed to land:

2 Likes