*This post is part of a series on Mohammad Anwar’s excellent Perl Weekly Challenge, where Perl and Raku hackers submit solutions to two different challenges every week. (It’s a lot of fun, if you’re into that sort of thing.)*

Task #2 this week asks us to (and I quote): print all **Palindrome Dates** between **2000** and **2999**. The format of date is **mmddyyyy**. For example, the first one was on **October 2, 2001** as it is represented as **10022001**.

It’s pretty easy to avoid using any sort of date library with a couple of key observations about the problem domain. First, we’ll split it up into month (`mm`

), day (`dd`

), century (`cc`

), and 2-digit year (`yy`

). Thus our “baseline” date format is `mm dd cc yy`

.

If we use `R[xx]`

as shorthand for “string reverse of **xx**“, we can rewrite the date in a couple of different ways:

mm dd cc yy # Original R[yy] R[cc] cc yy # Start with year mm dd R[dd] R[mm] # Start with mm/dd R[yy] dd R[dd] yy # Start with yy and dd

I didn’t list all of the possible combinations. The last one is the one I’m interested in, because:

Since the month is the reverse of the year, and months range from 01..12, that means `yy`

must be limited to 01..12, each reversed (10, 20, 30, … 11, 21).

Since the century is the reverse of the day, and the century varies from 20..29, there are only three possible days (`dd`

) that work: 02, 12, and 22.

Furthermore, we don’t need to check for days in a month, leap years, or any of that Julian nonsense, because all of our `dd`

s are less than the shortest possible month length of 28 days. (That’s also why we don’t need a date library.)

Thus, instead of checking every single date for a thousand years, we only need to iterate a total of 12 * 3 = 36 times, and this is the optimal number, meaning each time we loop, we can print a valid palindromic date. And, the way I’ve chosen to loop, the results will already be in sorted order.

## Raku

Raku makes things easy with the `X`

cross product operator, and the built-in ability to use n-at-a-time `-> $dd, $yy`

pointy blocks:

for (<02 12 22> X (1..12)».fmt('%02d')».flip.sort).flat -> $dd, $yy { say "{$yy.flip}-$dd-{$dd.flip}$yy"; }

## Perl

Perl isn’t far behind on expressiveness, though:

my @yy = sort map { chop . ($_||0) } 1..12; for my $dd (qw<02 12 22>) { for my $yy (@yy) { printf "%02d-%02d-%02d%02d\n", scalar reverse($yy), $dd, scalar reverse($dd), $yy; } }

The `chop`

is a bit of a cheeky way to go, here, to show another way of reversing a two-character string. Since I know all of the strings in that `map`

will be two characters, I’m just removing the last character and concatenating the remainder, which is another way of saying `scalar reverse`

. I could have also done it with arithmetic, `substr`

, or at least half a dozen other ways.

## 02-02-2020 / 2020-02-02

February 2nd this year (Groundhog Day, in some countries) was super-duper-extra special, as it was a palindromic date whether you interpret it as **mm/dd/yyyy**, **dd/mm/yyyy**, or even **yyyy/mm/dd**. The last one of these was quite a while ago.