# Perl Weekly Challenge 171: numbers and refenreces

It is sad that, after more than two years of me doing Raku, I still don’t have any production code project to work on. Therefore, in order to keep my coding and Raku-ing (is that a term?) knowdledge, I try to solve every Perl Weekly Challenge tasks.

In the following, the assigned tasks for Challenge 171.

and for the sake of some Perl 5, let’s do some stuff also in PostgreSQL Pl/Perl:
Last, the solutions in PostgreSQL PL/PgSQL:

## PWC 171 - Task 1

This task was about to compute the first 20 odd abundant numbers, those that have a sum of divisors greater than the number itself.

``````sub is-abundant( Int:D \$n ) {
my @divisors = 1;
@divisors.push: \$_ if \$n %% \$_ for ( 2 .. \$n / 2 );
return @divisors.sum > \$n;
}

sub MAIN() {
my @abundant = lazy gather {
take \$_ if \$_ !%% 2 && is-abundant( \$_ ) for ( 1 .. Inf );
};

@abundant[ 0 .. 20 ].join( "\n" ).say;
}

``````

I decided to create an `is-abundant` function that extracts all the divisors, put them int the `@divisors` array and sum them, returning if the sum if greater or not than the original number.
Then, in the `MAIN`, I `lazy gather` over all numbers and provide only those odd and that are abundant.

## PWC 171 - Task 2

I’m not sure I’ve correctly understood the task. The task was requiring you to make a function that accepts two functions and returns the result of invoking them in a nested way.

``````sub compose( Sub:D \$f, Sub:D \$g ) {
return sub (*@a) {
"F( G( { @a } ) )".say;
\$f( \$g( @a ) )
};
}

sub MAIN() {
my \$f = sub (*@a) {
"F( { @a } )".say;
return @a;
};
my \$g = sub (*@a) {
"G( { @a } )".say;
return @a;
};

my \$h = compose( \$f, \$g );
\$h( 'PWC 171' );
}

``````

I produced two function, `\$f` and `\$g` that both slurp their arguments and return them unmodified. Of course, in real like, such functions are going to do something. Then `compose` accepts two defined `Sub` references and invokes them in a nested way.

## PWC 171 - Task 1 in PostgreSQL PL/Perl

A translation of the Raku solution:

``````CREATE OR REPLACE FUNCTION
RETURNS SETOF INT
AS \$CODE\$
my (\$limit) = @_;

my \$is_abundant = sub {
my ( \$n ) = @_;
my @divisors = ( 1 );

for ( 2 .. \$n / 2 ) {
next if \$n % \$_ != 0;
push @divisors, \$_;
}

my \$sum = 0;
\$sum += \$_ for ( @divisors );

return \$sum > \$n;
};

for ( 1 .. 99999 ) {
next if \$_ % 2 == 0;
if ( \$is_abundant->( \$_ ) ) {
\$limit--;
return_next( \$_ );
}

last if \$limit <= 0;
}

return undef;

\$CODE\$
LANGUAGE plperl;

``````

The `\$is_abundant` code references implements the function that sums all divisors of the given odd number and returns true if the number is abundant. Then, the main loop does a `return_next` to append a new number to the result set in the case it is abundant.

## PWC 171 - Task 2 in PostgreSQL PL/Perl

Assuming I understood the tast, theimplementation is just a crafted `SELECT`:

``````CREATE OR REPLACE FUNCTION
RETURNS TEXT
AS \$CODE\$
elog( DEBUG, "F( \$_ )" );
return \$_;
\$CODE\$
LANGUAGE plperl;

CREATE OR REPLACE FUNCTION
RETURNS TEXT
AS \$CODE\$
elog( DEBUG, "G( \$_ )" );
return \$_;
\$CODE\$
LANGUAGE plperl;

/*
DEBUG:  G( Hello World )
DEBUG:  F( Hello World )
--------------
Hello World
*/
CREATE OR REPLACE FUNCTION
RETURNS TEXT
AS \$CODE\$

my \$compose = sub {
my \$query = sprintf( "SELECT %s( %s( '%s' ) ) AS compose;",
\$_[ 0 ],
\$_[ 1 ],
\$_[ 2 ] );
elog( DEBUG, "Query [\$query]" );
my \$result_set = spi_exec_query( \$query );
return \$result_set->{ rows }[ 0 ]->{ compose };
};

return \$compose->( @_ );
\$CODE\$
LANGUAGE plperl;

``````

I wrote a couple of functions, `f` and `g` just to use to test the machinery.
The main function build a crafted nested `SELECT` that invokes all the functions in the right order, and then returns the result outside. Why using an anonymous code reference? Well, because if you want to transform that into a set returning function is easier!

## PWC 171 - Task 1 in PostgreSQL PL/PgSQL

Quite same approach as in the PL/Perl solution:

``````CREATE OR REPLACE FUNCTION
pwc171.task1_plpgsql( l int DEFAULT 20 )
RETURNS SETOF INT
AS \$CODE\$
DECLARE
s int := 0;
i int;
d int;
BEGIN
FOR i IN  2 .. 99999  LOOP
IF i % 2 = 0 THEN
CONTINUE;
END IF;
s := 0;
FOR d in  2 .. ( i / 2 )  LOOP
IF i % d = 0 THEN
s := s + d;
END IF;
END LOOP;

IF s > i THEN
RETURN NEXT i;
l := l - 1;

IF l = 0 THEN
RETURN;
END IF;
END IF;
END LOOP;
RETURN;
END
\$CODE\$
LANGUAGE plpgsql;

``````

The only different with the Perl and Raku solutions is that I don’t care about divisors, but keep only the sum of them while processing them.

## PWC 171 - Task 2 in PostgreSQL PL/PgSQL

Easy enough to be done with a simple query:

``````CREATE OR REPLACE FUNCTION
v text DEFAULT 'PWC 171' )
RETURNS SETOF TEXT
AS \$CODE\$
BEGIN
RETURN QUERY
EXECUTE format( 'SELECT * FROM %s( %s( \$\$%s\$\$ ) )', f, g, v );
END
\$CODE\$
LANGUAGE plpgsql;

``````

The `EXECUTE` accepts a dynamically built query, built on top of `format()` (a kind of `printf`) that does the `SELECT` of the nested functions. Note the usage of dollar quoting `\$\$` around the function argument to escape it in already quoted string.

The article Perl Weekly Challenge 171: numbers and references has been posted by Luca Ferrari on June 27, 2022