AoC 2022/25 - Wind down, hot air up!

TL;DR

On with Advent of Code puzzle 25 from 2022: the last day is always bittersweet!

So… this year’s series of puzzles is at the end, and it’s bittersweet. On the one hand, regaining some time for the rest of everyday life is refreshing; on the other, the puzzles are terrific and I’ll miss them for the coming eleven months.

As in the past, the 25th day only contains part 1, where the second part’s star is provided for free. The puzzle itself is about doing calculations in a modified base 5, where values are symmetric around 0 (i.e. we consider -2, -1, 0, 1, and 2 instead of 0, 1, 2, 3, 4 as in a regular base-5). The specific codename for this modified base in the puzzle is SNAFU.

Solutions around were mainly divided into two camps:

  • moving to base 10, doing the maths, moving back to base SNAFU, or
  • doing calculations directly in base SNAFU.

I decided to go the first route, so we have to code two functions. Moving from SNAFU to base 10 is pretty straightforward, as we only have to do the proper calculations and it’s basically a base change without specific differences:

sub snafu-to-b10 ($snafu) {
   state %value-for = "=" => -2, '-' => -1, '0' => 0, '1' => 1, '2' => 2;
   my $weight = 1;
   return $snafu.comb.reverse.map(
      {
         my $part = $weight * %value-for{$_};
         $weight *= 5;
         $part;
      }
   ).sum;
}

Going back to SNAFU is a bit more challenging, but not really. At each step, we calculate the rest modulo 5 like any base change, except that we take the right symbol based on the value and we update the residual part accordingly (sometimes adding values instead of subtracting).

sub b10-to-snafu ($decimal is copy) {
   state %symbol-for = 0 => '0', 1 => '1', 2 => '2', 3 => '=', 4 => '-';
   (
      gather while $decimal > 0 {
         my $rest = $decimal % 5;
         take %symbol-for{$rest};
         $decimal = ($decimal - ($rest > 2 ?? $rest - 5 !! $rest)) div 5;
      }
   ).reverse.join('');
}

With these function available, it’s easy to code the solution:

sub part1 ($inputs) { b10-to-snafu($inputs.map({snafu-to-b10($_)}).sum); }

And that’s it! Thanks for enduring all of this, and have fun!


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