I’ve been doing the Weekly
Challenges. The
latest
involved various progressions based on factorials. (Note that this is
open until 27 February 2022.)
To try to maintain my polyglot mindset, I shuffle the languages
I'll be writing the solution in (because I tend to solve the problem
in the first one and then copy the algorithm to the others). This time
the first one was PostScript, which was fun… at least now that I've
got some idea of how to debug it.
Task 1: Left Factorials
Write a script to compute Left Factorials of 1 to 10. Please refer
OEIS A003422 for more information.
This turns out to be: the left factorial of N is the sum of all
factorials of 0 to N-1.
For efficiency, I calculate those lower factorials just once as
needed: the only time I need to know the value of 5! is when I'm
calculating term 6, and at that point I already know the value of 4!
because I used it to calculate the previous term.
Thus in JavaScript:
function leftfactorial (mx) {
let out=[];
let fact=1;
let sum=0;
for (let i=0; i < mx; i++) {
if (i>0) {
fact *= i;
}
sum += fact;
out.push(sum);
}
return out;
}
Task 2: Factorions
You are given an integer, $n.
Write a script to figure out if the given integer is a factorion.
A factorion is a natural number that equals the sum of the
factorials of its digits.
Of course it's in the OEIS. And the
trivial version would thus be a lookup for the four values; but let's
take this seriously and work it out the slightly harder way. Raku:
sub factorion($input) {
Special-casing zero saves trouble later.
if ($input == 0) {
return False;
}
Calculate each digit's factorial. (We may not use all of them but I
think that any slight increase in calculation time is justified by the
reduced complexity of this approach.)
my @fd;
@fd.push(1);
my $ff=1;
for (1..9) -> $i {
$ff *= $i;
@fd.push($ff);
}
Now extract the digits and sum their factorial values.
my $working=$input;
my $dsum=0;
while ($working > 0) {
$dsum += @fd[$working % 10];
$working=floor($working/10);
}
Return the boolean calculation.
return $input==$dsum;
}
One could short-cut if dsum
gets larger than input
but it hardly
seems worth it.
Full code on
github.
Comments on this post are now closed. If you have particular grounds for adding a late comment, comment on a more recent post quoting the URL of this one.