## Advent Calendar - December 11, 2022

Sunday, Dec 11, 2022| Tags: Perl, Raku

## Advent Calendar 2022

### |   Day 10   |   Day 11   |   Day 12   |

The gift is presented by `Flavio Poletti`. Today he is talking about his solution to “The Weekly Challenge - 153”. This is re-produced for Advent Calendar 2022 from the original post by him.

## PWC153 - Factorions

### TL;DR

On with TASK #2 from The Weekly Challenge `#153`. Enjoy!

## The challenge

You are given an integer, `\$n`.

Write a script to figure out if the given integer is factorion.

A factorion is a natural number that equals the sum of the factorials of its digits.

### Example 1

``````Input: \$n = 145
Output: 1

Since 1! + 4! + 5! => 1 + 24 + 120 = 145
``````

### Example 2

``````Input: \$n = 123
Output: 0

Since 1! + 2! + 3! => 1 + 2 + 6 <> 123
``````

## The questions

… does the challenge puzzle say anything about the base we are supposed to consider for figuring out the digits? Is base 10 fair enough?

## The solution

OK, let’s start with a blunt implementation of the test in Perl:

``````#!/usr/bin/env perl
use v5.24;
use warnings;
use experimental 'signatures';
no warnings 'experimental::signatures';
use List::Util 'sum';

say is_factorion(shift // 145) ? 1 : 0;

sub is_factorion (\$n) {
state \$f = [ 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 ];
\$n == sum map { \$f->[\$_] } split m{}mxs, \$n;
}
``````

We only need factorials `up to 9` here, so it makes sense to avoid implementing the factorial function altogether and use a `state` variable to keep them.

Now, let’s switch the brain on.

It’s intuitive that there can be only a finite amount of factorions, whatever the base. As an example, in base 10 the maximum contribution to the sum is from digit 9, which provides a whopping `362880`. Not bad, but it’s still a finite and limited contribution to be compared against exponentially growing numbers as we add more digits.

So, for example, the sequence of `9999999` (seven 9) yields a sum of all factorials of the digits that is a mere `2540160` (seven digits, but clearly less than the original). As a matter of fact, it’s impossible to go beyond `2540160` with seven digits, and eight digits or more numbers are of course out of reach.

So… it makes sense to look for all factorions in base 10:

``````#!/usr/bin/env perl
use v5.24;
use warnings;
use experimental 'signatures';
no warnings 'experimental::signatures';
use List::Util 'sum';

# find out the limit. With a given amount of 9 we can only go "some"
# far, so there's no point going beyond that maximum point.
my \$s = '';
while ('necessary') {
\$s .= '9';
last if \$s > sumfact(\$s);
}

# find out all factorions (up to that limit)
for my \$n (0 .. sumfact(\$s)) {
say \$n if \$n == sumfact(\$n);
}

sub sumfact (\$n) {
state \$f = [ 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 ];
sum map { \$f->[\$_] } split m{}mxs, \$n;
}
``````

It seems that there are not that many:

``````1
2
145
40585
``````

This leads us to our Raku solution:

``````#!/usr/bin/env raku
use v6;
sub MAIN (Int:D \$n = 145) { put is-factorion(\$n) ?? 1 !! 0 }

sub is-factorion (Int:D \$n where \$n >= 0) {
state %factorions = set(1, 2, 145, 40585);
return \$n ∈ %factorions;
}
``````

So cool!

If you have any suggestion then please do share with us perlweeklychallenge@yahoo.com.

## SO WHAT DO YOU THINK ?

If you have any suggestions or ideas then please do share with us.