Perl Weekly Challenge 142: divide and sleep!
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 142.
And this week, as for the previous PWC, I had time to quickly implement the tasks also on PostgreSQL
plpgsql
language:
PWC 142 - Task 1
The first task was quite easy to solve: given two numbers, find out all the divisors of the former one that end with the second number. One row to rule the rask:sub MAIN( Int $m where { $m > 1 }
, Int $n where { $n > 0 && $m > $n } ) {
( 1 .. $m ).grep( $m %% * ).grep( * ~~ / ^ \d* $n $ / ).elems.say;
}
The idea is simple: I produce all the numbers from
1
to $m
, the number I must seek the divisors of. Then I do grep
all the numbers keeping only those that are “real” divisors, and then I do grep
again searching for a regular expression that makes the given divisor ending with the $n
digit.
At the end, I count the found elements and output the value.
PWC 142 - Task 2
The second task was about implementing the sleep sort, a simple and resource-consuming sort mechanism that requires the creation of one thread for every value to sort. Each thread has to sleep for the specified time according to the value it has to sort, and then the thread emits the value. In this way, apart from the time required to create the threads, each value will be emitted sorted.Promise
s are the way to go in Raku:
sub MAIN( *@n where { @n.grep( * ~~ Int ).elems == @n.elems } ) {
my @threads;
for @n -> $sleep {
@threads.push: Promise.in( $sleep.Int ).then( { $sleep.say } );
}
await @threads;
}
I do create a list of
@threads
, each one attached to a Promise
that will be kept in
the sepcified amount of seconds. Once the promise is kept, the value “attached” to the promise will be printed on standard output. And then the program waits for all the promises to finish.
It is important to note that the variable
$sleep
as to be made explicit, because $_
within the then
block of the Promise
will result in the promise itself.
PWC 142 - Task 1 in PostgreSQL plpgsql
A recursive CTE could solve the problem:
CREATE OR REPLACE FUNCTION
f_divisors_last_digit( m int, n int )
RETURNS SETOF int
AS $CODE$
WITH RECURSIVE numbers AS (
SELECT 1 as num
UNION
SELECT num + 1
FROM numbers
WHERE num + 1 <= m )
, divisors AS (
SELECT num as div
FROM numbers
WHERE m % num = 0 )
SELECT count(*)
FROM divisors
WHERE div::text LIKE ( '%' || n::text );
$CODE$
LANGUAGE sql;
The
numbers
part generates the sequence of all the numbers from 1
to m
, and corresponds to the ( 1 .. $m)
part in the Raku solution. The divisors
part excludes from numbers
those that are not divisors of m
, and correspond to the grep( $m %% * )
part in Raku.
Last, the final SELECT
counts all the divisors that end with n
using LIKE
, that is the SQL way to search for a pattern matching.
PWC 142 - Task 2 in PostgreSQL `plpgsql**
There is no way to implement threading in PostgreSQL, and this is because the database must decide how many threads (or better, processes) to launch. Remember: SQL is a declarative language .However, there is a way to simulate the same behavior by means of opening a connection for every number to sort, make the connection to sleep and then print out the value.
This is quite easy to achieve with
psql
capabilities:
#!/bin/sh
for i in $*; do
psql -At -c "SELECT pg_sleep( $i ); SELECT $i;" &
done
The
-At
instruments psql
to start the unaligned mode and print out only the results, without any header. The -c
tells psql
to execute immediatly the following SQL statement, that is made by two parts:
pg_sleep()
is a function that tells the connection to sleep for the specified amount of seconds;SELECT
prints out the specified number.
Last, every
psql
instance is pushed to background, so to continue with the following number to sort.