Perl Weekly Challenge: Week 197
I'm back from my trip to India and eager to catch up with the challenges I missed while I was gone. So without further ado...
Challenge 1:
Move Zero
You are given a list of integers,
@list
.Write a script to move all zero, if exists, to the end while maintaining the relative order of
non-zero
elements.
Example 1
Input: @list = (1, 0, 3, 0, 0, 5)
Output: (1, 3, 5, 0, 0, 0)
Example 2
Input: @list = (1, 6, 4)
Output: (1, 6, 4)
Example 3
Input: @list = (0, 1, 0, 2, 0)
Output: (1, 2, 0, 0, 0)
This one is pretty straightforward.
First we set up two arrays, one to hold the 0's and one for every other number.
my @zeros;
my @numbers;
Then we iterate through the elements of @list
.
for @list -> $i {
If the value of the element is 0, we add it to the @zeros
array...
if $i == 0 {
@zeros.push($i)
...or if it isn't we add it to the @numbers
array.
} else {
@numbers.push($i)
}
}
Finally we append @zeros
to @numbers
(remembering to flatten the appended values with |
.) The rest of
this line is to make the output look like that in the spec.
say q{(}, @numbers.push(| @zeros).join(q{, }), q{)};
This is the Perl version which works the same way.
my @zeros;
my @numbers;
for my $i (@list) {
if ($i == 0) {
push @zeros, $i;
} else {
push @numbers, $i;
}
}
push @numbers, @zeros;
say q{(}, (join q{, }, @numbers), q{)};
Challenge 2:
Wiggle Sort
You are given a list of integers,
@list
.Write a script to perform
Wiggle Sort
on the given list.Wiggle sort would be such as list[0] < list[1] > list[2] < list[3]….
Example 1
Input: @list = (1,5,1,1,6,4)
Output: (1,6,1,5,1,4)
Example 2
Input: @list = (1,3,2,2,3,1)
Output: (2,3,1,3,1,2)
Umm, I'm not sure I got this one right but anyway here is my attempt in Raku.
It feels a bit like cheating if we use .sort()
to implement a sort algorithm but this
seemed to be the easiest way to get all the elements of @list
in numeric order, smallest value to largest.
@list = @list.sort({ $^a <=> $^b });
The middle element of the sorted list is identified.
my $mid = @list.elems div 2;
An array is declared to hold the wiggle sorted array.
my @sorted;
We will also need to know if our @list
has an odd number of elements or not.
my $odd = @list.elems % 2 == 1;
If there are an odd number of elements, the first one to be added to @sorted
.
if $odd {
@sorted.push(@list[$mid]);
}
Next, we are going to add pairs of elements to @sorted
. one element will be from
the beginning of @list
up to its midpoint, and the other will be from the end of @list
down to the midpoint. If the number of elements is odd, the pair is added in the order larger, smaller;
if not, the order is smaller, larder.
for 0 ..^ $mid -> $i {
if $odd {
@sorted.push(@list[@list.end - $i], @list[$i]);
} else {
@sorted.push(@list[$i], @list[@list.end - $i]);
}
}
Now we have a wiggle sorted list. All that remains is to print it in the format the spec suggests.
say q{(}, @sorted.join(q{,}), q{)};
My code gives the same answer for example 1 as shown there. But for example 2 it gives (1,3,1,3,2,2)
. I believe
this is still correct if we assume the spec really means <=
and >=
when it mentions <
and >
. Is this a
valid assumption to make? I don't know but I'm going with it.
for reference, here is the Perl version which works the same and has the same flaws.
my @list = sort { $a <=> $b } @ARGV;
my $mid = scalar @list / 2;
my @sorted;
my $odd = scalar @list % 2 == 1;
if ($odd) {
push @sorted, $list[$mid];
}
for my $i (0 .. $mid - 1) {
if ($odd) {
push @sorted, $list[scalar @list - $i - 1], $list[$i];
} else {
push @sorted, $list[$i], $list[scalar @list - $i - 1];
}
}
say q{(}, (join q{,}, @sorted), q{)};