This is my response to the Perl Weekly Challenge #142.
$m
and $n
.
$m
having last
digit $n
.
Input: $m = 24, $n = 2
Output: 2
The divisors of 24 are 1, 2, 3, 4, 6, 8 and 12.
There are only 2 divisors having last digit 2 are 2 and 12.
Example 2:
Input: $m = 30, $n = 5
Output: 2
The divisors of 30 are 1, 2, 3, 5, 6, 10 and 15.
There are only 2 divisors having last digit 5 are 5 and 15.
The «diviors» procedure, last used a week ago (Challenge #141.1: Number Divisors), comes in handy yet again:
File: dld
#! /usr/bin/env raku
subset PosInt of Int where * >= 1; # [1]
subset Digit of Int where * == any(0..9); # [2]
unit sub MAIN (PosInt $m, Digit $n, :v(:$verbose));
my @divisors = divisors($m); # [3]
my @result = @divisors.grep({ /$n$/ }) ; # [4]
say ": - Ending with $n: { @result.join(", ") }" if $verbose;
say @result.elems;
sub divisors ($number, :$not-self, :$not-one) # [3]
{
my @divisors;
for ($not-one ?? 2 !! 1) .. $number/2 -> $candidate
{
@divisors.push: $candidate if $number %% $candidate;
}
@divisors.push: $number unless $not-self;
say ": $number has { @divisors.elems } divisors: { @divisors.join(", ") }"
if $verbose; # [3a]
return @divisors;
}
[1] Ensure positive integers.
[2] A single digit is better than the «positive integers» specified by the challenge, Note that zero is allowed here, whereas the challenge excluded it.
[3] Get the divisors. Note the slightly altered verbose output (in [3a]) compared to the previous version.
[4] Only use the numbers ending with the specified digit.
Running it:
$ ./dld 24 2
2
$ ./dld 30 5
2
With verbose mode:
$ ./dld -v 24 2
: 24 has 8 divisors: 1, 2, 3, 4, 6, 8, 12, 24
: - Ending with 2: 2, 12
2
$ ./dld -v 30 5
: 30 has 8 divisors: 1, 2, 3, 5, 6, 10, 15, 30
: - Ending with 5: 5, 15
2
Write a script to implement Sleep Sort. For more information, please checkout this post.
The linked to page talks about milliseconds, so let us have a go at that:
File: sleep-sort-milliseconds
#! /usr/bin/env raku
unit sub MAIN (*@values where @values.elems > 0, :v(:$verbose)); # [1]
my @promises; # [5]
for @values -> $value # [2]
{
next unless $value ~~ Numeric; # [3]
@promises.push: Promise.in($value / 1000).then: { say $value; }; # [4][5]
}
await @promises; # [5a]
[1] Ensure at least one element. Note the missing type check, as we do that in the loop instead.
[2] For each value,
[3] Skip it if it is not numeric.
[4] Set up a Promise
to run in (after) the specified
number of seconds. The input is in milliseconds, so we divide by 1000 to get the number
of seconds. The result is that the code block in when
is executed after
the specified time. Not necessarily at the time, but sometime after it.
[5] The Promise
calls returns a Promise object, that
we can use to e.g. inspect the state. We have to collect them, as done here, so that
we can ensure that that the program does not finish before they are executed (or kept,
as it is called) - as future promises dies at program termination. We do this wait
with the await
keyword.
See
docs.raku.org/routine/await
for more information about await
.
Running it:
$ ./sleep-sort-milliseconds 5 4 3 1 2 0.9
1
0.9
5
3
2
4
That was not quite as we could hope for. The problem is that milliseconds are too quick, and/or Raku too slow.
Let us have a go at the more relaxing seconds instead:
File: sleep-sort
#! /usr/bin/env raku
unit sub MAIN (*@values where @values.elems > 0, :v(:$verbose));
my @promises;
for @values -> $value
{
next unless $value ~~ Numeric;
@promises.push: Promise.in($value).then: { say $value; };
}
await @promises;
Running it:
$ ./sleep-sort 5 4 3 1 2 0.9
0.9
1
2
3
4
5
That is more like it.
Note that the program will wait as long as it takes, if left alone. A very large value will give a program that will run for a long time. E.g.:
$ ./sleep-sort 5 4 3 1 2 0.9 1234567890
The program will go on (doing nothing much) for slightly less than 40 years. Feel free to check for yourself…
And that's it.