Advent of Code 2017 Day 3 part 2 was quite the gruelling exercise. We needed to locate the first memory value larger than the input we are given. The memory locations store an accumulative value (still spiralled) based on its existing neighbours. This is the example given.
147 142 133 122 59 304 5 4 2 57 330 10 1 1 54 351 11 23 25 26 362 747 806---> ...
Location one still starts at 1. Location two only has one neighbour with a value of 1, so it get’s a value of 1.
Location three gets a value of 2 since it has neighbours one and two in which both have a value of 1.
2 1 1
Location four has a value of 4. This is because it has three, two, and 1 as neighbours. We then continue on to generate the rings.
Once we get passed the initial ring, we can use some general rules to generate the values. At most a memory location will have 4 active neighbours. It came down to identifying the unique location requirements.
Since a location may potentially have neighbours in its own ring and the previous ring, we need to keep the last ring generated. I initially thought about the convoluted code that would need to be created, but decided to use Active Patterns.
I was able to determine the points of interest by using some of the data I had obtained from part 1. Specifically the row length. This allowed me to identify whether I was in a corner, before the corner, or after the corner. Once that was established I needed to handle the first and last element in the ring. Everything else was considered general middle elements.
I’ve included a couple of helper functions to handle wrapping the previous array’s index and generating the index offset from the current ring to the previous.
I opted to use mutation for generating a ring. I have my active patterns in the pattern match to help with code readability.
With all the building blocks in place I can now create a sequence of memory values based on the spiral structure.
memoryValues |> Seq.take 12 |> Seq.toList;; val it : int list = [1; 1; 2; 4; 5; 10; 11; 23; 25; 26; 54; 57]
The part was to take the first element greater than my input.