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!