Perl Weekly Challenge: Week 320
Challenge 1:
Maximum Count
You are given an array of integers.
Write a script to return the maximum between the number of positive and negative integers. Zero is neither positive nor negative.
Example 1
Input: @ints = (-3, -2, -1, 1, 2, 3)
Output: 3
There are 3 positive integers.
There are 3 negative integers.
The maximum between 3 and 3 is 3.
Example 2
Input: @ints = (-2, -1, 0, 0, 1)
Output: 2
There are 1 positive integers.
There are 2 negative integers.
The maximum between 2 and 1 is 2.
Example 3
Input: @ints = (1, 2, 3, 4)
Output: 4
There are 4 positive integers.
There are 0 negative integers.
The maximum between 4 and 0 is 4.
This is another job for a Raku one-liner, well, if you stretch the meaning of one line a little bit. In fact my solution consists of two statements; for didactic purposes, I'll show them as two sperate lines. Just pretend they are one. :-)
Raku's List
class has a poweful method called .classify()
that takes elements and adds them to a Hash
depending
on the criteria we set. Here, if the element is negative, it gets added to the n
key of %a
. If it is positive,
it will be added to the p
key. If it is zero, it gets added to the z
key which we will subsequently ignore.
@*ARGS.classify({ $_ < 0 ?? "n" !! $_ > 0 ?? "p" !! "z" }, :into(my %a));
Now we can count the number of elements in %a<p>
and %a<n>
with .elems()
, find the maximum of the two with .max()
and print the result with .say()
.
(%a<p>.elems, %a<n>.elems).max.say;
Perl doesn't have .classify()
so we have to emulate it. However as we don't need all its' bells and whistles we can
simplify a little bit.
Instead of a Hash
we just define two variable to store the count of positive negatives.
my $neg = 0;
my $pos = 0;
That's another difference; as we iterate through the elements of @ints
we increment counts rather than store the element
itself as Raku did. Also we can ignore zeros.
for my $int (@ints) {
if ($int < 0) {
$neg++;
} elsif ($int > 0) {
$pos++;
}
}
We also need to provide our own imlementation of ,max()
.
say max($neg, $pos);
Challenge 2:
Sum Difference
You are given an array of positive integers.
Write a script to return the absolute difference between digit sum and element sum of the given array.
Example 1
Input: @ints = (1, 23, 4, 5)
Output: 18
Element sum: 1 + 23 + 4 + 5 => 33
Digit sum: 1 + 2 + 3 + 4 + 5 => 15
Absolute difference: | 33 - 15 | => 18
Example 2
Input: @ints = (1, 2, 3, 4, 5)
Output: 0
Element sum: 1 + 2 + 3 + 4 + 5 => 15
Digit sum: 1 + 2 + 3 + 4 + 5 => 15
Absolute difference: | 15 - 15 | => 0
Example 3
Input: @ints = (1, 2, 34)
Output: 27
Element sum: 1 + 2 + 34 => 37
Digit sum: 1 + 2 + 3 + 4 => 10
Absolute difference: | 37 - 10 | => 27
This one is also a Raku one-liner. We use the command-line arguments to provide input. Finding the element sum is dead simple; we just use the .sum()
method. From this amount we have to subtract the digit sum which is slightly more complicated. We use .map()
to iterate over the integers and run .comb()
on each one to split it into individual digits. This will give us a List
of List
s so we use .flat()
to "flatten" them into one list. Finally .sum()
is used again.
say @*ARGS.sum - @*ARGS.map({ $_.comb }).flat.sum
Unfortunately we can't make a one-liner in Perl because we need to provide our own implentation of .sum()
. But the
core of the script is one line. (And we don't have to deal with flattening arrays.)
say sum(@ints) - sum(map { split //, $_ } @ints);