# ETOOBUSY ðŸš€ minimal blogging for the impatient

# Advent of Code 2020 - Day 13

**TL;DR**

Puzzle 13 in this yearâ€™s Advent of Code was interesting.

First of all, thanks to @riffraff for indirectly reminding me about Advent of Code:

Am I the only one feeling the #AdventOfCode puzzles this year have been simpler than in the past, until day 9 at least?

I was interested, and I even discovered that I already participated into
Advent of Code *five years ago*. The blessing of forgetting!

When I arrived to the second part of puzzle 13, the three words
Chinese Remainder Theorem formed as a reflex in my memory. *The blessing
of remembering*.

Well, donâ€™t get me wrong: I only know *more or less* what the theorem is
about, and in particular that itâ€™s useful to address systems of congruences.
Thatâ€™s enough, though, because I can go and read it time and again when it
pops up in my mind. The blessing of Wikipedia.

So hereâ€™s my solution in all its cryptic glory, without the I/O part:

```
#!/usr/bin/env perl
use 5.024;
use warnings;
use experimental qw< postderef signatures >;
no warnings qw< experimental::postderef experimental::signatures >;
use List::Util 'reduce';
use bigint;
my @buses = split m{[,\s]+}mxs, '7,13,x,x,59,x,31,19';
my $overall = reduce {crt($a->@*, $b->@*)}
map { [$buses[$_], ($buses[$_] - $_) % $buses[$_]] }
grep { $buses[$_] ne 'x' } 0 .. $#buses;
say "result for part2: $overall->[1]";
sub crt ($n1, $r1, $n2, $r2) {
my ($gcd, $x, $y) = egcd($n1, $n2);
die "not coprime! <$n1> <$n2>" if $gcd != 1;
my $N = $n1 * $n2;
my $r = ($r2 * $x * $n1 + $r1 * $y * $n2) % $N;
return [$N, $r];
}
sub egcd { # https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
my ($X, $x, $Y, $y, $A, $B, $q) = (1, 0, 0, 1, @_);
while ($A) {
($A, $B, $q) = ($B % $A, $A, int($B / $A));
($x, $X, $y, $Y) = ($X, $x - $q * $X, $Y, $y - $q * $Y);
}
return ($B, $x, $y);
} ## end sub egcd
```

Function `egcd`

comes straight from The extended Euclidâ€™s algorithm.

The function `crt`

implements the Chinese Remainder Theorem to find a
solution for a pair of congruences, giving back the *combined congruence*.
Itâ€™s really just a translation of the Wikipedia page into code, leveraging the `egcd`

function and making sure that the
two input values `$n1`

and `$n2`

are coprime.

Soâ€¦ we just have to unpack how we get `$overall`

, that will eventually
hold our solution. Letâ€™s put some line numbers:

```
1 my $overall = reduce {crt($a->@*, $b->@*)}
2 map { [$buses[$_], ($buses[$_] - $_) % $buses[$_]] }
3 grep { $buses[$_] ne 'x' } 0 .. $#buses;
```

We start from line 3: we iterate over the index in array `@buses`

, keeping
only those related to actual bus numbers (i.e. ignoring those whose bus is
set as `x`

).

In line 2 we transform each index into a pair of values: the first is the modulo number - that is the same as the bus number - while the second is the remainder. More on this a few lines down below.

In line 1 I finally get to use a function whose power I only suspect. It iterates over a list, where at each step applies a function that takes in input two values and produces one value. The two values are the first two elents in the list for the first call; afterwards, itâ€™s the result of the previous call and the next element in the list.

As we have to incrementally apply function `crt`

to get a single growing
congruenceâ€¦ it hits the nail right in the head.

Now letâ€™s come to line 2 again. As I said, the *modulo* number is the same
as the bus, so thereâ€™s nothing much to say here. On the other hand, the
remainder of our solution $s$ by the bus number is calculated as:

This can be explained like this: the index $i$ of the bus in the array represents the target time offset of the specific bus with respect to the first one. So, itâ€™s the remainder of the multiple of $b$ immediately following our solution $s$, modulo the solution $s$ itself:

\[k \cdot b = s + i \\\]On the other hand, weâ€™re interested into the rest of the division of $s$ by $b$. The relation above can be expressed as:

\[s = k \cdot b - i = (k - 1) \cdot b + (b - i) = k' \cdot b + (b - i)\]which tells us that:

\[s \equiv (b - 1) \pmod b\]i.e. the value that we exposed above and that we put as the second element in our pairs of line 1.

At this point, I hope I managed to intrigue you a bitâ€¦ happy coding!

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