ETOOBUSY 🚀 minimal blogging for the impatient
AoC 2021/5 - Hyperstuff
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!