### Perl Weekly Challenge: Week 171

#### Challenge 1:

Abundant Number

Write a script to generate first 20 `Abundant Odd Numbers`.

According to wikipedia,

A number n for which the sum of divisors σ(n) > 2n, or, equivalently, the sum of proper divisors (or aliquot sum) s(n) > n.

For example, `945` is the first `Abundant Odd Number`.

``````Sum of divisors:
1 + 3 + 5 + 7 + 9 + 15 + 21 + 27 + 35 + 45 + 63 + 105 + 135 + 189 + 315 = 975
``````

Fairly straightforward.

We start by defining a list to hold our results and the number to start searching from.

``````my @abundants;
my \$n = 1;
``````

Then until we have 20 odd abundant numbers...

``````until @abundants.elems == 20 {
``````

...we find all the divisors for the current value of `\$n`. A small optimizzation we can make is to stop searching for divisors at `\$n / 2`. Any divisors found will be stored in another list.

``````    my @divisors;
for 1 .. \$n / 2 -> \$i {
if \$n %% \$i {
@divisors.push(\$i);
}
}
``````

Once we have all the divisors, we total them and if the sum is greater than `\$n` we have an abundant number and we can store it.

``````    if ([+] @divisors) > \$n {
@abundants.push(\$n);
}
``````

And then no matter what the outcome was we move on to the next candidate number. As we are only interested in odd abundant numbers, we can do another little optimization and increment `\$n` by 2 thereby skipping even numbers.

``````    \$n += 2;
}
``````

Finally, the results are printed out nicely.

``````@abundants.join(q{, }).say;
``````

(Full code on Github.)

This is the Perl version. It is pretty much a 1-1 translation from Raku except I had to use my own `sum()` function instead of `[+]`.

``````my @abundants;
my \$n = 1;

until (scalar @abundants == 20) {
my @divisors;
for my \$i (1 .. \$n / 2) {
if (\$n % \$i == 0) {
push @divisors, \$i;
}
}

if (sum(\@divisors) > \$n) {
push @abundants, \$n;
}

\$n += 2;
}

say join q{, }, @abundants;
``````

(Full code on Github.)

The first 20 odd abundant numbers are:

``````945, 1575, 2205, 2835, 3465, 4095, 4725, 5355, 5775, 5985, 6435, 6615, 6825, 7245, 7425, 7875, 8085, 8415, 8505, 8925
``````

#### Challenge 2:

First-class Function

Create `sub compose(\$f, \$g)` which takes in two parameters `\$f` and `\$g` as subroutine refs and returns subroutine ref i.e. `compose(\$f, \$g)->(\$x) = \$f->(\$g->(\$x))`

e.g.

``````\$f = (one or more parameters function)
\$g = (one or more parameters function)

\$h = compose(\$f, \$g)
\$f->(\$g->(\$x,\$y, ..)) == \$h->(\$x, \$y, ..) for any \$x, \$y, ...
``````

An important concept in functional programming is that functions should be able to be used as data i.e stored in a variable or passed as an argument to another function etc. Languages which allow this sort of thing are said to have first-class functions. First-class functions can be used as basic building bricks to make new more complex functions. This is called composability.

Let's say we have two Perl functions:

`square()` takes one argument and returns it squared.

``````sub square {
my (\$x) = @_;

return \$x * \$x;
}
``````

`sum()` takes multiple arguments, adds them altogether and returns the result.

``````sub sum {
my \$total = 0;

for my \$elem (@_) {
\$total += \$elem;
}

return \$total;
}
``````

Now what if we wanted to do both? We could just call both functions like this:

``````say square(sum(1, 2, 3));
``````

but that's not very generic. What if requirements changed and we now want to multiply and square instead. We would have to write a `multiply()` function certainly but we would also have to review our codebase and change all the lines like the one above to:

``````say square(multiply(1,2,3));
``````

Which could be all over the place in a huge project.

Instead we can write a function like this:

``````sub compose {
``````

It starts by taking two references to functions as its' arguments.

``````    my (\$f, \$g) = @_;
``````

Then it creates a new anonymous subroutine that calls the function stored in `\$g` and then feeds the results into the function stored in `\$f`.

``````    return sub { \$f->(\$g->(@_)); };
}
``````

we call it like this:

``````say compose(\&square, \&sum)->(1,2,3);
``````

`\&` signifies a code reference. `\$f` and `\$g` could be `square()` and `sum()` or `square()` and `multiply()` or even `sum()` and `multiply()` etc. Or we can store the new subroutine in a variable like this:

``````my \$h = compose(\&square, \&sum);
say \$h->(1,2,3);
``````

If we use `\$h` everywhere, we can change `sum()` to `multiply()` once in the definition and not have to change any other line of code.

(Full Perl code on Github.)

This is the Raku version. It works the same way as Perl but has gotten rid of the unsightly `->`s.

``````sub compose(&f, &g) {

return sub (*@args) { &f(&g(@args)); };
}

sub square(Int \$x) {
return \$x * \$x;
}

sub sum(*@args) {
return [+] @args;
}

say compose(&square, &sum)(1,2,3);
``````

(Full Raku code on Github.)