aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad Sajid Anwar <Mohammad.Anwar@yahoo.com>2025-08-06 12:56:05 +0100
committerGitHub <noreply@github.com>2025-08-06 12:56:05 +0100
commit6d3ec14e8a0fd5c8a6a4eb54ba4c87ad64a52072 (patch)
tree9f2369f42306ed4a56f9b80d2150355a91da42ab
parent5687713d337d65d407daf7ad551a2eeecc867d3f (diff)
parentf4869f0492216173b20663bd548fffc38c912593 (diff)
downloadperlweeklychallenge-club-6d3ec14e8a0fd5c8a6a4eb54ba4c87ad64a52072.tar.gz
perlweeklychallenge-club-6d3ec14e8a0fd5c8a6a4eb54ba4c87ad64a52072.tar.bz2
perlweeklychallenge-club-6d3ec14e8a0fd5c8a6a4eb54ba4c87ad64a52072.zip
Merge pull request #12477 from PerlMonk-Athanasius/branch-for-challenge-333
Perl & Raku solutions to Tasks 1 & 2 for Week 333
-rw-r--r--challenge-333/athanasius/perl/ch-1.pl279
-rw-r--r--challenge-333/athanasius/perl/ch-2.pl176
-rw-r--r--challenge-333/athanasius/raku/ch-1.raku268
-rw-r--r--challenge-333/athanasius/raku/ch-2.raku168
4 files changed, 891 insertions, 0 deletions
diff --git a/challenge-333/athanasius/perl/ch-1.pl b/challenge-333/athanasius/perl/ch-1.pl
new file mode 100644
index 0000000000..0a5bfb3679
--- /dev/null
+++ b/challenge-333/athanasius/perl/ch-1.pl
@@ -0,0 +1,279 @@
+#!perl
+
+################################################################################
+=comment
+
+Perl Weekly Challenge 333
+=========================
+
+TASK #1
+-------
+*Straight Line*
+
+Submitted by: Mohammad Sajid Anwar
+
+You are given a list of co-ordinates.
+
+Write a script to find out if the given points make a straight line.
+
+Example 1
+
+ Input: @list = ([2, 1], [2, 3], [2, 5])
+ Output: true
+
+Example 2
+
+ Input: @list = ([1, 4], [3, 4], [10, 4])
+ Output: true
+
+Example 3
+
+ Input: @list = ([0, 0], [1, 1], [2, 3])
+ Output: false
+
+Example 4
+
+ Input: @list = ([1, 1], [1, 1], [1, 1])
+ Output: true
+
+Example 5
+
+ Input: @list = ([1000000, 1000000], [2000000, 2000000], [3000000, 3000000])
+ Output: true
+
+=cut
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2025 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=comment
+
+Interface
+---------
+1. If no command-line arguments are given, the test suite is run. Otherwise:
+2. A non-empty list of coordinate strings is entered on the command-line.
+3. If the first coordinate string begins with a hyphen (because the x-coordin-
+ ate is negative), it must be preceded by "--" to indicate that it is not a
+ command-line flag.
+
+Assumptions
+-----------
+1. The coordinates represent points on the Cartesian plane; therefore, coordin-
+ ate values are real numbers.
+2. Degenerate cases: if there are only 1 or 2 (distinct) coordinates, they are
+ deemed to be collinear.
+
+Note
+----
+This script handles real number co-ordinate values using Perl's built-in float-
+ing-point arithmetic. For this reason, equality comparison cannot be performed
+reliably using the "==" operator; instead, an equal_values() subroutine is pro-
+vided. If the absolute difference between the values to be compared is less than
+a given $EPSILON, then the values are considered equal.
+
+=cut
+#===============================================================================
+
+use v5.32; # Enables strictures
+use warnings;
+use Const::Fast;
+use Regexp::Common qw( number );
+use Test::More;
+
+const my $EPSILON => 1e-10;
+const my $USAGE => <<END;
+Usage:
+ perl $0 [<list> ...]
+ perl $0
+
+ [<list> ...] A non-empty list of co-ordinate strings (e.g., "1 2" "3 4")
+END
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\nChallenge 333, Task #1: Straight Line (Perl)\n\n";
+}
+
+#===============================================================================
+MAIN:
+#===============================================================================
+{
+ if (scalar @ARGV == 0)
+ {
+ run_tests();
+ }
+ else
+ {
+ my @list = @ARGV;
+ my $coords = get_coords( \@list );
+
+ printf "Input: \@list = (%s)\n",
+ join ', ', map { '[' . join( ', ', @$_ ) . ']' } @$coords;
+
+ my $collinear = are_collinear( $coords );
+
+ printf "Output: %s\n", $collinear ? 'true' : 'false';
+ }
+}
+
+#-------------------------------------------------------------------------------
+sub are_collinear
+#-------------------------------------------------------------------------------
+{
+ my ($list) = @_;
+ my $coords = remove_duplicates( $list );
+
+ if (scalar @$coords > 2)
+ {
+ my $x0 = $coords->[ 0 ][ 0 ];
+ my $y0 = $coords->[ 0 ][ 1 ];
+ my $x1 = $coords->[ 1 ][ 0 ];
+ my $y1 = $coords->[ 1 ][ 1 ];
+ my $m0 = equal_values( $x0, $x1 ) ? undef : ($y1 - $y0) / ($x1 - $x0);
+
+ for my $i (2 .. $#$coords)
+ {
+ my $xi = $coords->[ $i ][ 0 ];
+ my $yi = $coords->[ $i ][ 1 ];
+ my $lhs = $xi; # Assume the line is vertical
+ my $rhs = $x0;
+
+ if (defined $m0) # It's not
+ {
+ $lhs = ($yi - $y0) / ($xi - $x0);
+ $rhs = $m0;
+ }
+
+ return '' unless equal_values( $lhs, $rhs );
+ }
+ }
+
+ return 1;
+}
+
+#-------------------------------------------------------------------------------
+sub remove_duplicates
+#-------------------------------------------------------------------------------
+{
+ my ($list) = @_;
+ my @unique;
+
+ for my $coord (@$list)
+ {
+ my $found = '';
+
+ for my $uniq (@unique)
+ {
+ if (equal_coords( $uniq, $coord ))
+ {
+ $found = 1;
+ last;
+ }
+ }
+
+ push @unique, $coord unless $found;
+ }
+
+ return \@unique;
+}
+
+#-------------------------------------------------------------------------------
+sub equal_coords
+#-------------------------------------------------------------------------------
+{
+ my ($p, $q) = @_;
+
+ return equal_values( $p->[ 0 ], $q->[ 0 ] ) &&
+ equal_values( $p->[ 1 ], $q->[ 1 ] );
+}
+
+#-------------------------------------------------------------------------------
+sub equal_values
+#-------------------------------------------------------------------------------
+{
+ my ($x, $y) = @_;
+
+ return abs( $x - $y ) < $EPSILON;
+}
+
+#-------------------------------------------------------------------------------
+sub get_coords
+#-------------------------------------------------------------------------------
+{
+ my ($list) = @_;
+ my @coords;
+
+ for my $str (@$list)
+ {
+ my @pair = grep { / \S /x } split / \s+ /x, $str;
+
+ scalar @pair == 2 or error( qq[Invalid coordinate string "$str"] );
+
+ for (@pair)
+ {
+ / ^ $RE{num}{real} $ /x
+ or error( qq["$_" is not a valid coordinate value] );
+ }
+
+ push @coords, [ map { $_ + 0 } @pair ]; # Normalize the coord values
+ }
+
+ return \@coords;
+}
+
+#-------------------------------------------------------------------------------
+sub run_tests
+#-------------------------------------------------------------------------------
+{
+ print "Running the test suite\n";
+
+ while (my $line = <DATA>)
+ {
+ chomp $line;
+
+ my ($test_name, $coord_str, $expected) = split / \| /x, $line;
+
+ for ($test_name, $coord_str, $expected)
+ {
+ s/ ^ \s+ //x;
+ s/ \s+ $ //x;
+ }
+
+ my @list = split / ; /x, $coord_str;
+ my $coords = get_coords( \@list );
+ my $collinear = are_collinear( $coords ) ? 'true' : 'false';
+
+ is $collinear, $expected, $test_name;
+ }
+
+ done_testing;
+}
+
+#-------------------------------------------------------------------------------
+sub error
+#-------------------------------------------------------------------------------
+{
+ my ($message) = @_;
+
+ die "ERROR: $message\n$USAGE";
+}
+
+################################################################################
+
+__DATA__
+Example 1 | 2 1; 2 3; 2 5 |true
+Example 2 | 1 4; 3 4; 10 4 |true
+Example 3 | 0 0; 1 1; 2 3 |false
+Example 4 | 1 1; 1 1; 1 1 |true
+Example 5 |1000000 1000000; 2000000 2000000; 3000000 3000000|true
+Duplicate 1| 1 2; 1 2; 2 3; 3 4 |true
+Duplicate 2| 1 2; 1 2; 2 3; 3 5 |false
+Duplicate 3| 1 2; 1 2; 2 3; 1 2 |true
+Singleton | 4 9 |true
+Pair | 4 9; 7 6 |true
+Reals |-1.5 0.3; -2.5 -0.7; -3.5 -1.7 |true
diff --git a/challenge-333/athanasius/perl/ch-2.pl b/challenge-333/athanasius/perl/ch-2.pl
new file mode 100644
index 0000000000..553630be28
--- /dev/null
+++ b/challenge-333/athanasius/perl/ch-2.pl
@@ -0,0 +1,176 @@
+#!perl
+
+################################################################################
+=comment
+
+Perl Weekly Challenge 333
+=========================
+
+TASK #2
+-------
+*Duplicate Zeros*
+
+Submitted by: Mohammad Sajid Anwar
+
+You are given an array of integers.
+
+Write a script to duplicate each occurrence of zero, shifting the remaining
+elements to the right. The elements beyond the length of the original array are
+not written.
+
+Example 1
+
+ Input: @ints = (1, 0, 2, 3, 0, 4, 5, 0)
+ Output: (1, 0, 0, 2, 3, 0, 0, 4)
+
+ Each zero is duplicated.
+ Elements beyond the original length (like 5 and last 0) are discarded.
+
+Example 2
+
+ Input: @ints = (1, 2, 3)
+ Output: (1, 2, 3)
+
+ No zeros exist, so the array remains unchanged.
+
+Example 3
+
+ Input: @ints = (1, 2, 3, 0)
+ Output: (1, 2, 3, 0)
+
+Example 4
+
+ Input: @ints = (0, 0, 1, 2)
+ Output: (0, 0, 0, 0)
+
+Example 5
+
+ Input: @ints = (1, 2, 0, 3, 4)
+ Output: (1, 2, 0, 0, 3)
+
+=cut
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2025 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=comment
+
+Interface
+---------
+1. If no command-line arguments are given, the test suite is run. Otherwise:
+2. A non-empty list of integers is entered on the command-line.
+
+=cut
+#===============================================================================
+
+use v5.32; # Enables strictures
+use warnings;
+use Const::Fast;
+use Regexp::Common qw( number );
+use Test::More;
+
+const my $USAGE => <<END;
+Usage:
+ perl $0 [<ints> ...]
+ perl $0
+
+ [<ints> ...] A non-empty list of integers
+END
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\nChallenge 333, Task #2: Duplicate Zeros (Perl)\n\n";
+}
+
+#===============================================================================
+MAIN:
+#===============================================================================
+{
+ if (scalar @ARGV == 0)
+ {
+ run_tests();
+ }
+ else
+ {
+ my @ints = @ARGV;
+
+ for (@ints)
+ {
+ / ^ $RE{num}{int} $ /x or error( qq["$_" is not a valid integer] );
+ }
+
+ printf "Input: \@ints = (%s)\n", join ', ', @ints;
+
+ my $dups = duplicate_zeros( \@ints );
+
+ printf "Output: (%s)\n", join ', ', @$dups;
+ }
+}
+
+#-------------------------------------------------------------------------------
+sub duplicate_zeros
+#-------------------------------------------------------------------------------
+{
+ my ($ints) = @_;
+ my @dups;
+
+ for my $int (@$ints)
+ {
+ push @dups, $int;
+ push @dups, 0 if $int == 0;
+ }
+
+ return [ @dups[ 0 .. $#$ints ] ];
+}
+
+#-------------------------------------------------------------------------------
+sub run_tests
+#-------------------------------------------------------------------------------
+{
+ print "Running the test suite\n";
+
+ while (my $line = <DATA>)
+ {
+ chomp $line;
+
+ my ($test_name, $int_str, $exp_str) = split / \| /x, $line;
+
+ for ($test_name, $int_str, $exp_str)
+ {
+ s/ ^ \s+ //x;
+ s/ \s+ $ //x;
+ }
+
+ my @ints = split / \s+ /x, $int_str;
+ my @exps = split / \s+ /x, $exp_str;
+ my $dups = duplicate_zeros( \@ints );
+
+ is_deeply $dups, \@exps, $test_name;
+ }
+
+ done_testing;
+}
+
+#-------------------------------------------------------------------------------
+sub error
+#-------------------------------------------------------------------------------
+{
+ my ($message) = @_;
+
+ die "ERROR: $message\n$USAGE";
+}
+
+################################################################################
+
+__DATA__
+Example 1|1 0 2 3 0 4 5 0|1 0 0 2 3 0 0 4
+Example 2|1 2 3 |1 2 3
+Example 3|1 2 3 0 |1 2 3 0
+Example 4|0 0 1 2 |0 0 0 0
+Example 5|1 2 0 3 4 |1 2 0 0 3
diff --git a/challenge-333/athanasius/raku/ch-1.raku b/challenge-333/athanasius/raku/ch-1.raku
new file mode 100644
index 0000000000..c20475cdae
--- /dev/null
+++ b/challenge-333/athanasius/raku/ch-1.raku
@@ -0,0 +1,268 @@
+use v6d;
+
+################################################################################
+=begin comment
+
+Perl Weekly Challenge 333
+=========================
+
+TASK #1
+-------
+*Straight Line*
+
+Submitted by: Mohammad Sajid Anwar
+
+You are given a list of co-ordinates.
+
+Write a script to find out if the given points make a straight line.
+
+Example 1
+
+ Input: @list = ([2, 1], [2, 3], [2, 5])
+ Output: true
+
+Example 2
+
+ Input: @list = ([1, 4], [3, 4], [10, 4])
+ Output: true
+
+Example 3
+
+ Input: @list = ([0, 0], [1, 1], [2, 3])
+ Output: false
+
+Example 4
+
+ Input: @list = ([1, 1], [1, 1], [1, 1])
+ Output: true
+
+Example 5
+
+ Input: @list = ([1000000, 1000000], [2000000, 2000000], [3000000, 3000000])
+ Output: true
+
+=end comment
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2025 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=begin comment
+
+Interface
+---------
+1. If no command-line arguments are given, the test suite is run. Otherwise:
+2. A non-empty list of coordinate strings is entered on the command-line.
+3. If the first coordinate string begins with a hyphen (because the x-coordin-
+ ate is negative), it must be preceded by "--" to indicate that it is not a
+ command-line flag.
+
+Assumptions
+-----------
+1. The coordinates represent points on the Cartesian plane; therefore, coordin-
+ ate values are real numbers.
+2. Degenerate cases: if there are only 1 or 2 (distinct) coordinates, they are
+ deemed to be collinear.
+
+Note
+----
+The difficulties of equality comparison using floating-point arithmetic (see the
+Perl solution to this Task) are here avoided by representing real number co-
+ordinate values as instances of the built-in Raku class Rat.
+
+=end comment
+#===============================================================================
+
+use Test;
+
+subset Coord of List where (Rat, Rat);
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ "\nChallenge 333, Task #1: Straight Line (Raku)\n".put;
+}
+
+#===============================================================================
+multi sub MAIN
+(
+ *@list #= A non-empty list of co-ordinate strings (e.g., "1 2" "3 4")
+)
+#===============================================================================
+{
+ my Coord @coords = get-coords( @list );
+
+ "Input: \@list = (%s)\n".printf:
+ @coords.map( { '[' ~ .join( ', ' ) ~ ']' } ).join: ', ';
+
+ my Bool $collinear = are-collinear( @coords );
+
+ "Output: %s\n".printf: $collinear ?? 'true' !! 'false';
+}
+
+#===============================================================================
+multi sub MAIN() # No input: run the test suite
+#===============================================================================
+{
+ run-tests();
+}
+
+#-------------------------------------------------------------------------------
+sub are-collinear( List:D[Coord:D] $list --> Bool:D )
+#-------------------------------------------------------------------------------
+{
+ my Coord @coords = remove-duplicates( $list );
+
+ if @coords.elems > 2
+ {
+ my Rat $x0 = @coords[ 0; 0 ];
+ my Rat $y0 = @coords[ 0; 1 ];
+ my Rat $x1 = @coords[ 1; 0 ];
+ my Rat $y1 = @coords[ 1; 1 ];
+ my Rat $m0 = ($x0 == $x1) ?? Rat !! ($y1 - $y0) / ($x1 - $x0);
+
+ for 2 .. @coords.end -> UInt $i
+ {
+ my Rat $xi = @coords[ $i; 0 ];
+ my Rat $yi = @coords[ $i; 1 ];
+ my Rat $lhs = $xi; # Assume the line is vertical
+ my Rat $rhs = $x0;
+
+ if $m0.defined # It's not
+ {
+ $lhs = ($yi - $y0) / ($xi - $x0);
+ $rhs = $m0;
+ }
+
+ return False unless $lhs == $rhs;
+ }
+ }
+
+ return True;
+}
+
+#-------------------------------------------------------------------------------
+sub remove-duplicates( List:D[Coord:D] $list --> List:D[Coord:D] )
+#-------------------------------------------------------------------------------
+{
+ my Coord @unique;
+
+ for @$list -> Coord $coord
+ {
+ my Bool $found = False;
+
+ for @unique -> Coord $uniq
+ {
+ if equal( $uniq, $coord )
+ {
+ $found = True;
+ last;
+ }
+ }
+
+ @unique.push: $coord unless $found;
+ }
+
+ return @unique;
+}
+
+#-------------------------------------------------------------------------------
+sub equal( Coord:D $p, Coord:D $q --> Bool:D )
+#-------------------------------------------------------------------------------
+{
+ return $p[ 0 ] == $q[ 0 ] && $p[ 1 ] == $q[ 1 ];
+}
+
+#-------------------------------------------------------------------------------
+sub get-coords( List:D[Str:D] $list --> List:D[Coord:D] )
+#-------------------------------------------------------------------------------
+{
+ my Coord @coords;
+
+ for @$list -> Str $str
+ {
+ my Str @pair = $str.split: / \s+ /, :skip-empty;
+
+ @pair.elems == 2 or error( qq[Invalid coordinate string "$str"] );
+
+ for @pair
+ {
+ .Rat // error( qq["$_" is not a valid coordinate value] );
+ }
+
+ @coords.push: [ @pair.map: { .Rat } ];
+ }
+
+ return @coords;
+}
+
+#-------------------------------------------------------------------------------
+sub run-tests()
+#-------------------------------------------------------------------------------
+{
+ 'Running the test suite'.put;
+
+ for test-data.lines -> Str $line
+ {
+ my Str ($test-name, $coord-str, $expected) = $line.split: / \| /;
+
+ for $test-name, $coord-str, $expected
+ {
+ s/ ^ \s+ //;
+ s/ \s+ $ //;
+ }
+
+ my Coord @coords = get-coords( [ $coord-str.split: ';' ] );
+ my Str $collinear = are-collinear( @coords ) ?? 'true' !! 'false';
+
+ is $collinear, $expected, $test-name;
+ }
+
+ done-testing;
+}
+
+#-------------------------------------------------------------------------------
+sub error( Str:D $message )
+#-------------------------------------------------------------------------------
+{
+ "ERROR: $message".put;
+
+ USAGE();
+
+ exit 0;
+}
+
+#-------------------------------------------------------------------------------
+sub USAGE()
+#-------------------------------------------------------------------------------
+{
+ my Str $usage = $*USAGE;
+
+ $usage ~~ s:g/ ($*PROGRAM-NAME) /raku $0/;
+
+ $usage.put;
+}
+
+#-------------------------------------------------------------------------------
+sub test-data( --> Str:D )
+#-------------------------------------------------------------------------------
+{
+ return q:to/END/;
+ Example 1 | 2 1; 2 3; 2 5 |true
+ Example 2 | 1 4; 3 4; 10 4 |true
+ Example 3 | 0 0; 1 1; 2 3 |false
+ Example 4 | 1 1; 1 1; 1 1 |true
+ Example 5 |1000000 1000000; 2000000 2000000; 3000000 3000000|true
+ Duplicate 1| 1 2; 1 2; 2 3; 3 4 |true
+ Duplicate 2| 1 2; 1 2; 2 3; 3 5 |false
+ Duplicate 3| 1 2; 1 2; 2 3; 1 2 |true
+ Singleton | 4 9 |true
+ Pair | 4 9; 7 6 |true
+ Reals |-1.5 0.3; -2.5 -0.7; -3.5 -1.7 |true
+ END
+}
+
+################################################################################
diff --git a/challenge-333/athanasius/raku/ch-2.raku b/challenge-333/athanasius/raku/ch-2.raku
new file mode 100644
index 0000000000..04c0410f74
--- /dev/null
+++ b/challenge-333/athanasius/raku/ch-2.raku
@@ -0,0 +1,168 @@
+use v6d;
+
+################################################################################
+=begin comment
+
+Perl Weekly Challenge 333
+=========================
+
+TASK #2
+-------
+*Duplicate Zeros*
+
+Submitted by: Mohammad Sajid Anwar
+
+You are given an array of integers.
+
+Write a script to duplicate each occurrence of zero, shifting the remaining
+elements to the right. The elements beyond the length of the original array are
+not written.
+
+Example 1
+
+ Input: @ints = (1, 0, 2, 3, 0, 4, 5, 0)
+ Output: (1, 0, 0, 2, 3, 0, 0, 4)
+
+ Each zero is duplicated.
+ Elements beyond the original length (like 5 and last 0) are discarded.
+
+Example 2
+
+ Input: @ints = (1, 2, 3)
+ Output: (1, 2, 3)
+
+ No zeros exist, so the array remains unchanged.
+
+Example 3
+
+ Input: @ints = (1, 2, 3, 0)
+ Output: (1, 2, 3, 0)
+
+Example 4
+
+ Input: @ints = (0, 0, 1, 2)
+ Output: (0, 0, 0, 0)
+
+Example 5
+
+ Input: @ints = (1, 2, 0, 3, 4)
+ Output: (1, 2, 0, 0, 3)
+
+=end comment
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2025 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=begin comment
+
+Interface
+---------
+1. If no command-line arguments are given, the test suite is run. Otherwise:
+2. A non-empty list of integers is entered on the command-line.
+3. If the first integer is negative, it must be preceded by "--" to indicate
+ that it is not a command-line flag.
+
+=end comment
+#===============================================================================
+
+use Test;
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ "\nChallenge 333, Task #2: Duplicate Zeros (Raku)\n".put;
+}
+
+#===============================================================================
+multi sub MAIN
+(
+ #| A non-empty list of integers
+
+ *@ints where { .elems > 0 && .all ~~ Int:D }
+)
+#===============================================================================
+{
+ "Input: \@ints = (%s)\n".printf: @ints.join: ', ';
+
+ my Int @dups = duplicate-zeros( @ints );
+
+ "Output: (%s)\n"\.printf: @dups.join: ', ';
+}
+
+#===============================================================================
+multi sub MAIN() # No input: run the test suite
+#===============================================================================
+{
+ run-tests();
+}
+
+#-------------------------------------------------------------------------------
+sub duplicate-zeros( List:D[Int:D] $ints --> List:D[Int:D] )
+#-------------------------------------------------------------------------------
+{
+ my Int @dups;
+
+ for @$ints -> Int $int
+ {
+ @dups.push: $int;
+ @dups.push: 0 if $int == 0;
+ }
+
+ return @dups[ ^$ints.elems ];
+}
+
+#-------------------------------------------------------------------------------
+sub run-tests()
+#-------------------------------------------------------------------------------
+{
+ 'Running the test suite'.put;
+
+ for test-data.lines -> Str $line
+ {
+ my Str ($test-name, $int-str, $exp-str) = $line.split: / \| /;
+
+ for $test-name, $int-str, $exp-str
+ {
+ s/ ^ \s+ //;
+ s/ \s+ $ //;
+ }
+
+ my Int @ints = $int-str.split( / \s+ /, :skip-empty ).map: { .Int };
+ my Int @exps = $exp-str.split( / \s+ /, :skip-empty ).map: { .Int };
+ my Int @dups = duplicate-zeros( @ints );
+
+ is-deeply @dups, @exps, $test-name;
+ }
+
+ done-testing;
+}
+
+#-------------------------------------------------------------------------------
+sub USAGE()
+#-------------------------------------------------------------------------------
+{
+ my Str $usage = $*USAGE;
+
+ $usage ~~ s:g/ ($*PROGRAM-NAME) /raku $0/;
+
+ $usage.put;
+}
+
+#-------------------------------------------------------------------------------
+sub test-data( --> Str:D )
+#-------------------------------------------------------------------------------
+{
+ return q:to/END/;
+ Example 1|1 0 2 3 0 4 5 0|1 0 0 2 3 0 0 4
+ Example 2|1 2 3 |1 2 3
+ Example 3|1 2 3 0 |1 2 3 0
+ Example 4|0 0 1 2 |0 0 0 0
+ Example 5|1 2 0 3 4 |1 2 0 0 3
+ END
+}
+
+################################################################################