The day ten Advent of Code challenge gives us a list of points and velocity pairs. Each point is updated by its corresponding velocity every second. At some point in time, these points will converge and spell out a message. Our task is to find that message using the J programming language!

As usual, we’ll start by loading our input and massaging it into a form we can work with:

    replacements =. 'position=<';'';',';'';'> velocity=<';' ';'>';'';'-';'_'
    path =.  '/Users/pcorey/advent_of_code_2018/day_10/input'
    input =. ". > cutopen replacements rplc~ (1!:1) < path

I’m using a trick I learned from zxw on Twitter to easily replace and reformat the data before passing it into the “numbers” verb (".).

Next let’s write a tick verb that updates each point with its corresponding velocity. We’ll also keep track of the maximum spread between Y coordinate values and return that as the second value in a boxed tuple along with our next set of points and velocities:

    tick =. 3 : 0
      input =. 0 {:: y
      prev =. 1 {:: y
      next =. +/"1 |:"2 (2 2 $ ])"1 input
      max =. >./ 1 {"1 next
      min =. <./ 1 {"1 next
      diff =. | max - min
      if. diff < prev do.
        (next (0 1})"1 input);diff
      else.
        y
      end.
    )

Notice that if applying the next tick results in a lower spread, we return the new values. Otherwise, we return the old values. This means we can “converge” (^:_) on a result for this verb. The result we converge on will be the set of points with the lowest spread in the vertical dimension.

It turns out that this is our answer!

We can use J’s viewmat library to quickly visualize our answer (after some more rotating and massaging):

    load 'viewmat'

    to_mat =. 3 : 0
      min_x =. <./ 0 {"1 y
      min_y =. <./ 1 {"1 y
      max_x =. >./ 0 {"1 y
      max_y =. >./ 1 {"1 y
      coords =. 0 1 {"1 y
      coords =. (min_x,min_y) -~"1 coords
      mat =. ((1 + | max_y - min_y),(1 + | max_x - min_x)) $ 0
      updates =. (<@:;/@:|.)"1 coords
      1 updates} mat
    )

    viewmat to_mat 0 {:: tick^:_ input;_

The stars align.

Part Two

Part two turned out to be a simple modification of our part one solution. The challenge asked us to return how many ticks we went through before we found our message.

All we need to do to figure this out is to add a third element to the tuple we pass in and out of tick that holds an incrementing count:

    tick =. 3 : 0
      input =. 0 {:: y
      prev =. 1 {:: y
      count =. 2 {:: y
      next =. +/"1 |:"2 (2 2 $ ])"1 input
      max =. >./ 1 {"1 next
      min =. <./ 1 {"1 next
      diff =. | max - min
      if. diff < prev do.
        (next (0 1})"1 input);diff;(count + 1)
      else.
        y
      end.
    )

    2 {:: tick^:_ input;_;0

The answer to our challenge is the value of this final count.