ETOOBUSY 🚀 minimal blogging for the impatient
PWC197 - Move Zero
TL;DR
Here we are with TASK #1 from The Weekly Challenge #197. Enjoy!
The challenge
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)
The questions
Should we preserve the input @list
or should we modify it in-place?
I’ll go with the modification alternative.
The solution
The algorithm will be the same:
- iterate using an index in the array, starting from index 0
- if the current index points to a zero, it is removed (via
splice
) and the index is kept still (because the rest of the array shifts to the left) - otherwise, we advance the index.
Raku:
#!/usr/bin/env raku
use v6;
sub MAIN (*@args) {
@args = <1 0 3 0 0 5>».Int unless @args;
put '(', move-zero-in-place(@args).join(', '), ')';
}
sub move-zero-in-place (@list) {
my $i = 0;
my $n-zeros = 0;
while $i < @list {
if @list[$i] == 0 {
++$n-zeros;
@list.splice($i, 1);
}
else { ++$i }
}
@list.push: |(0 xx $n-zeros);
return @list;
}
Perl:
#!/usr/bin/env perl
use v5.24;
use warnings;
use experimental 'signatures';
no warnings 'experimental::signatures';
@ARGV = qw< 1 0 3 0 0 5 > unless @ARGV;
move_zero_in_place(\@ARGV);
{ local $" = ', '; say "(@ARGV)" }
sub move_zero_in_place ($list) {
my $i = 0;
my $n_zeros = 0;
while ($i < $list->@*) {
if ($list->[$i] == 0) {
++$n_zeros;
splice $list->@*, $i, 1;
}
else { ++$i }
}
push $list->@*, (0) x $n_zeros;
return $list;
}
Stay safe folks!