Peter
Peter Campbell Smith

Move and wiggle

Weekly challenge 197 — 26 December 2022

Week 197: 26 Dec 2022

Task 1

Task — 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.

Examples


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)

Analysis

The simplest way to do this is to move all the non-zeroes sequentially into a new array, appending the zeroes at the end.

And that's what I did.

I toyed with swapping then around in place, but while that (minimally) saves memory it is substantially slower.

Try it 

Try running the script with any input:



example: 6, 5, 4, 3, 0, 2, 1

Script


#!/usr/bin/perl

# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

use v5.26;    # The Weekly Challenge - 2022-12-26
use utf8;     # Week 197 - task 1 - Move zero
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';

move_zero(1, 0, 2, 0, 3, 4, 0);
move_zero(1, 2, 3, 4);
move_zero(0, 0, 0, 0);
move_zero(0, 0, 0, 0, 1);

sub move_zero {
    
    my (@list, @new, $i, $zeroes);
    
    @list = @_;
    $zeroes = 0;
    
    # copy non-zeroes, count zeroes
    for $i (@list) {
        if ($i) {
            push(@new, $i);
        } else {
            $zeroes ++;
        }
    }
    
    # append zeroes
    push @new, 0 for 0 .. $zeroes - 1;
    
    say qq[\nInput:  \@list = ] . join(', ', @list);
    say qq[Output:         ] . join(', ', @new);
}

Output


Input:  @list = 1, 0, 2, 0, 3, 4, 0
Output:         1, 2, 3, 4, 0, 0, 0

Input:  @list = 1, 2, 3, 4
Output:         1, 2, 3, 4

Input:  @list = 0, 0, 0, 0
Output:         0, 0, 0, 0

Input:  @list = 0, 0, 0, 0, 1
Output:         1, 0, 0, 0, 0

 

Any content of this website which has been created by Peter Campbell Smith is in the public domain