RabbitFarm
2023-01-08
Prime the Gaps!
The examples used here are from the weekly challenge problem statement and demonstrate the working solution.
Part 1
You are given a list of integers, @list. Write a script to find the total pairs in the sorted list where 2 consecutive elements has the max gap. If the list contains less then 2 elements then return 0.
Solution
use v5.36;
sub largest_gap{
my(@numbers) = @_;
my $gap = -1;
map{ $gap = $numbers[$_] - $numbers[$_ - 1] if $numbers[$_] - $numbers[$_ - 1] > $gap } 1 .. @numbers - 1;
return $gap;
}
sub gap_pairs{
my(@numbers) = @_;
return 0 if @numbers < 2;
my $gap = largest_gap(@numbers);
my $gap_count;
map { $gap_count++ if $numbers[$_] - $numbers[$_ - 1] == $gap } 1 .. @numbers - 1;
return $gap_count;
}
MAIN:{
say gap_pairs(3);
say gap_pairs(2, 5, 8, 1);
}
Sample Run
$ perl perl/ch-1.pl
0
2
Notes
Probably these two subroutines could be combined into one without too much trouble, but it still seems cleaner to me this way.
Do an initial pass over the list to determine the largest gap.
Perform a second pass over the list and count up all pairs which have the maximum gap.
An interesting issue came up. I've been trying to avoid the use of a map in a void context. This is just due to the general principal to use map as a function and use its return value rather than rely on side effects.
As part of this reformative effort I have been doing more with for in a postfix position. I discovered this when working this problem:
{say $_ if $_ % 2 == 0} for 0 .. 9
will not work. Perl gets confused by the
postfix if
within the block, apparently.
But there is a work around! Add do
and all is well.
do {say $_ if $_ % 2 == 0} for 0 .. 9
Of course the equivalent map
works just fine as you'd
expect map {say $_ if $_ % 2 == 0} 0 .. 9)
E. Choroba pointed out this is due to postfix
for
being a statement modifier which doesn't know what to do with blocks. But why does
do
fix this? I am still unclear on why that is. Even with the do
it's still a block!
Apparently perl will view it as a statement, for the purposes of the postfix for
?
UPDATE: Turns out that the do {}
construct qualifies as a Simple Statement. From the
perldoc: Note that there are
operators like eval {}, sub {}, and do {} that look like compound statements, but
aren't--they're just TERMs in an expression--and thus need an explicit termination when
used as the last item in a statement.
Part 2
You are given an integer $n > 0. Write a script to print the count of primes less than $n.
Solution
use v5.36;
use Math::Primality q/is_prime/;
sub prime_count{
return 0 + grep { is_prime $_ } 2 .. $_[0] - 1;
}
MAIN:{
say prime_count(10);
say prime_count(15);
say prime_count(1);
say prime_count(25);
}
Sample Run
$ perl perl/ch-2.pl
4
6
0
9
Notes
The Math::Primality module makes this quite easy! In fact, I am not sure there is that much to elaborate on. Check primality using is_prime() and we're done!
References
posted at: 19:30 by: Adam Russell | path: /perl | permanent link to this entry