Perl Weekly Challenge: Week 91
Advent of Code update: I'm starting to fall behind. I'm still determined to finish it though. If you like, you can see my Raku solutions here. Thankfully, this weeks challenge wasn't very difficult; read on:
This weeks challenges:
Challenge 1:
Count Number
You are given a positive number $N
.
Write a script to count number and display as you read it.
Example 1
Input: $N = 1122234
Output: 21321314
as we read "two 1 three 2 one 3 one 4"
Example 2
Input: $N = 2333445
Output: 12332415
as we read "one 2 three 3 two 4 one 5"
Example 3
Input: $N = 12345
Output: 1112131415
as we read "one 1 one 2 one 3 one 4 one 5"
All we need to do here is to split the input number $N
into digits and traverse
the resulting array. When a consecutive run of a particular digits ends and another
begins, we print out the count and which number it was.
There needs to be special handling for the start i.e. when there is no range and
$current
is 0, and the very end which we deal with by adding an extra print()
outside
the loop.
This is the Perl version:
my $N = shift // die "Need a positive number.\n";
my $current = 0;
my $count = 0;
for my $i (split //, $N) {
if ($i == $current) {
$count++;
} else {
if ($current != 0) {
print "$count$current";
}
$current = $i;
$count = 1;
}
}
print "$count$current\n";
...and this is Raku. For fun, I decided not to just port the Perl version. Instead I used the .classify()
method. This gives
us a hash where the keys are the number of unique digits and the values are arrays of each time they occurred in $N
. So we can
sort the keys of this hash and print the count of each value and then its key and get the right answer.
Well, we will get the right answer if the digits in $N
are in ascending order as in the examples given with the problem. But later,
it occurred to me that it will go wrong if this condition isn't met. Take 221112
for instance. We should output 223112
(and the Perl version gets it right) but instead we get 3132
. Which just goes to show you the value of a comprehensive test suite!
sub MAIN(
Int $N #= a positive number.
) {
my %count = $N.comb.classify({ $_; });
for %count.keys.sort -> $k {
print %count{$k}.elems, $k;
}
print "\n";
}
Challenge 2:
Jump Game
You are given an array of positive numbers @N
, where value at each index determines how far you are allowed to jump further.
Write a script to decide if you can jump to the last index. Print 1 if you are able to reach the last index otherwise 0.
Example 1
Input: @N = (1, 2, 1, 2)
Output: 1
as we jump one place from index 0 and then twoe places from index 1 to reach the last index.
Example 2
Input: @N = (2,1,1,0,2)
Output: 0
it is impossible to reach the last index. as we jump two places from index 0 to reach index 2, followed by one place jump from index 2 to reach the index 3. once you reached the index 3, you can't go any further because you can only jump 0 position further.
We have a variable $current
which stores which element of @N
we are on. Then we keep incrementing $current
by the value of the $current
element. Now there are four possible outcomes.
$current
is not at the last element of @N
. In that case we do the increment thing again.
The value of the $current
element is 0. Then we have to exit with a 0 because we cannot move any further so we would be stuck in
an infinite loop.
If none of the previous conditions hold true, we are guaranteed to be at the last element so we can exit the loop and return 1.
This is the Perl implementation:
sub jump {
my @N = @_;
my $current = 0;
while ( $current < (scalar @N - 1)) {
$current += $N[$current];
if ($N[$current] == 0 || $current > scalar @N) {
return 0;
}
}
return 1;
}
say jump(@ARGV);
...and this is Raku:
sub jump(@N) {
my $current = 0;
while $current < @N.elems - 1 {
$current += @N[$current];
if @N[$current] == 0 || $current >= @N.elems {
return 0;
}
}
return 1;
}
sub MAIN(
*@N #= a positive number.
) {
say jump(@N);
}