TL;DR

On with Advent of Code puzzle 6 from 2021: solving with hyperoperators.

Today’s puzzle was “easier” from my point of view, in the sense that I had a precise idea of how to address it since the beginning. I will not show the initial solution, though, but a transformed version that gave me an occasion to look at hyperoperators.

``````sub part-all (\$filename where *.IO.e) {
my (%counts);;
for \$filename.IO.lines {
my (\$p1, \$p2) = .comb(/ \-? \d+ /).map: {[\$^x, \$^y]};
my \$deltas = \$p2 «-» \$p1;
\$deltas = \$deltas «/» \$deltas».abs.max;
my \$is-hv = ([*] @\$deltas) == 0; # is it horizontal/vertical?
\$p2 «+=» \$deltas; # move one step ahead to include it too
while \$p1 !~~ \$p2 {
%counts<over-1>{\$p1}++ if \$is-hv && %counts<1>{\$p1}++;
%counts<over-2>{\$p1}++ if           %counts<2>{\$p1}++;
\$p1 «+=» \$deltas;
}
}
return %counts<over-1 over-2>».keys».elems;
}
``````

The idea is to sweep through the inputs and use each line, then toss it away. The four input values are parsed via `.comb` and arranged into two arrays, which end up in `\$p1` and `\$p2` respectively. The `.map` comes handy here in providing us more than one element when we ask for them (via the circumflexed variables `\$^x` and `\$^y`, which act as indicators that the block of code passed to `map` takes two input parameters).

From here it’s all operations on points, represented as arrays of two values, thanks to the hyperoperators. It’s a bit weird that, with some [Matlab][] background from a lot of time ago, I didn’t catch with these operators before. Maybe Huffman was right: in [Matlab][] operations are upon vectors by default, and you have to put something additional to trigger a different behaviour; here the normal behaviour is the scalar one, and you have to put something additional to make it different.

Anyway, the `\$delta` array eventually contains how much we should “advance” in either coordinate to go from point `\$p1` up to point `\$p2`. To make sure we also include the input `\$p2`, it is itself increased once by the `\$delta`, so that we can iterate our `while` condition upon `\$p1` being different from `\$p2`.

A segment that is either horizontal or vertical will have one of the to differences/increments set to 0, so we can easily test for non-diagonal stuff by multiplying together the components of `\$delta`. This is how `\$is-hv` is initialized.

The hash `%counts` is populated in four different slots. The ones with shorter names `1` and `2` count the passage of a segment over the specific point, while the ones with longer names `over-1` and `over-2` keep track of those which see at least two segments intersect. This is later used to figure out the puzzle’s outputs.

At each loop, `\$p1` is advanced ahead at the end of the operations. This remembers me so much of C.

Well, I think it’s all for today… stay safe and have fun!

Comments? Octodon, , GitHub, Reddit, or drop me a line!