# Advent of Code Day 12 - sailing to a pause

This was another fun one. It took me some time to get the logic right (or left?), but in the end I came up with a nice solution. BTW, this will be the last daily blog post, as I'll have to finish some work projects, and start with some holiday projects.

#### Part 1

``````my @in  = map { [/^(\w)(\d+)\$/] } <>;
my @dir = qw(N E S W);
my \$cur = 1;
my \$r   = 0;
my \$c   = 0;``````

We again parse the map into a list of ops and values. Then we set up some things we'll need, like the list of directions and the current heading (`\$cur`) which is an index into the `dir-array`. `\$r` and `\$c` are the row and col where the ship currently is location (I prefer row/col to x/y).

``````my %ops;
%ops = (
N => sub { \$r -= shift },
S => sub { \$r += shift },
E => sub { \$c += shift },
W => sub { \$c -= shift },
F => sub { \$ops{ \$dir[\$cur] }(shift) },
L => sub { \$cur = ( \$cur - \$_ / 90 ) % 4 },
R => sub { \$cur = ( \$cur + \$_ / 90 ) % 4 },
);``````

Then we implement the ops. The first four simple move the ship around. `F` (forward) gets the current direction ("E" in the example), and calls the corresponding function. L and R where hard to get right. We calculate the number of turns (1, 2 or 3, depending on the degree value), and add or subtract it from the current index, using `mod` to stay inside the array of allowed directions (using negative modulus is always fun!)

``````for (@in) {
my ( \$op, \$val ) = @\$_;
\$ops{\$op}(\$val);
}
say abs( 0 - \$r ) + abs( 0 - \$c );``````

Finally we just need to go through the instruction set and call each op; and then calculate the Manhattan distance...

In my first version I used plain functions instead of the dispatch table, which I liked a bit better, but required me to turn off 'refs' strictures.

#### Part 2

Again it took me quite some time to understand the description, but after some scribbling and counting I figured it out.

``````my \$wr = -1;
my \$wc = 10;
my \$sr = 0;
my \$sc = 0;``````

For the second part, we "just" need to add a second set of coordinates for the waypoint (`\$wr, \$wc`).

``````my %ops;
%ops = (
N => sub { \$wr -= shift },
S => sub { \$wr += shift },
E => sub { \$wc += shift },
W => sub { \$wc -= shift },
F => sub { my \$val = shift; \$sr += \$val * \$wr; \$sc += \$val * \$wc },
R => sub { for ( 1 .. \$_ / 90 ) { ( \$wr, \$wc ) = ( \$wc, \$wr ); \$wc *= -1 } },
L => sub { for ( 1 .. \$_ / 90 ) { ( \$wr, \$wc ) = ( \$wc, \$wr ); \$wr *= -1 } },
);``````

The ops change a bit, mostly moving the waypoint around. `F` will move the ship. I used pen & paper to discover that to rotate the waypoint I need to switch row and col and (depending on the direction) change the sign on the row or col (i.e. multiply by -1). To switch row and col, we use a nice Perl trick to switch two values around using fancy list context: ( \$a, \$b ) = (\$b, \$a).

The rest of the code stays the same...