Are you playing along with Advent of Code? I got started a little late this year, so I’m doing a couple of days each day until I catch up.

The basis of of Code isn’t so much the beauty of your code as it is the correctness. Because of this, a lot of my code is hideously ugly, with design choices best described as “questionable”. For example, at one point, I used flatMap.count on returned optionals instead of returning zeroes and ones and reducing them with +. I’m using Swift because that’s the language that’s currently dominant in my brain, although a lot of the memory manipulation would have been easier with straight C.

I wanted to share my solution for the first half of day . The challenge stipulates a squared spiral pattern of numbers in a grid and then asks you to calculate the distance from each number to the center. The approach I came up with for I proved completely useless for the second half of day , where I had to start over from scratch. (Normally, you just modify the first code with an extra function and you go from part I to part II pretty easily.)

I took a road with part I that really didn’t fit the mindset of the challenge givers. For me, I was thinking geometrically, noticing that this was a degenerate case of a series of concentric circles. However instead of calculating the distance with a sin-cos solution, the concentric squares created a stepped triangle wave instead. Because of this, I built my solution to traverse the triangle wave and deduce the distance as the radius + the phase of the wave for any given number.

I thought I’d share my code for this because it’s pretty short and I think it’s pretty unusual for the problem domain.

for n in [24, 2, 23, 3205] {3;
    for i in sequence(first: , next: { $0 + 2 }) {3;
        // Find least bounding square that contains number3;
        let boundingSize = i * i3;
        if boundingSize >= n {3;
            // Start of the outer edge sequence3;
            let firstValue = (i - 2) * (i - 2) + 3;
            // Calculate distance to center3;
            let radius = (i - ) / 23;
            // The first number is always positioned at the3;
            // bottom right, one up from the bottom3;
            var current = radius - 3;
            // The `direction` differential is the basis of3;
            // the triangle wave generator. It flips at the3;
            // minimum (-radius) and maximum (radius) offsets3;
            var direction = -3;
            // One trip through the outer edge will be3;
            // sufficient to find the value3;
            for value in firstValue ... boundingSize {3;
                if value == n {3;
                    print("Result for (n) is (radius + abs(current))")3;
                // Generate the next value in the triangle3;
                // wave pattern to determine the distance3;
                // from the center3;
                current += direction3;
                if abs(current) == radius { direction *= - }3;

Needless to say, my solution for part II had nothing to do with this wave approach. Instead, I actually constructed the 2D array, populated it with numbers and then used those as an addressing scheme to collect sums. Outside the addressing, it was basically applying a 3×3 sum filter in an address-driven convolution. Much longer, not pretty, but reasonably effective.

In the end, if I had done my “fill then look up locations” approach I used for part II for the first puzzle, it would have provided a much quicker solution although I don’t think it would have been as short or, in my opinion, nifty.

What approach did you end up using for day 3? And what made you go with that design?

Source link


Please enter your comment!
Please enter your name here