aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad Sajid Anwar <Mohammad.Anwar@yahoo.com>2025-10-26 16:53:57 +0000
committerGitHub <noreply@github.com>2025-10-26 16:53:57 +0000
commit1a31fd09d296682306495e5bb315b9ee17d27344 (patch)
treea27ca0cdc11c35906837504d8ef6b55ee869a367
parentc1eb0d6242d0ff5ce7c8fc444385ed2b3db16af5 (diff)
parent446597e32e890881fe5774d5ef3af5379f633e1d (diff)
downloadperlweeklychallenge-club-1a31fd09d296682306495e5bb315b9ee17d27344.tar.gz
perlweeklychallenge-club-1a31fd09d296682306495e5bb315b9ee17d27344.tar.bz2
perlweeklychallenge-club-1a31fd09d296682306495e5bb315b9ee17d27344.zip
Merge pull request #12915 from PerlMonk-Athanasius/branch-for-challenge-344
Perl & Raku solutions to Tasks 1 & 2 for Week 344
-rw-r--r--challenge-344/athanasius/perl/ch-1.pl203
-rw-r--r--challenge-344/athanasius/perl/ch-2.pl265
-rw-r--r--challenge-344/athanasius/raku/ch-1.raku196
-rw-r--r--challenge-344/athanasius/raku/ch-2.raku289
4 files changed, 953 insertions, 0 deletions
diff --git a/challenge-344/athanasius/perl/ch-1.pl b/challenge-344/athanasius/perl/ch-1.pl
new file mode 100644
index 0000000000..59b61616ee
--- /dev/null
+++ b/challenge-344/athanasius/perl/ch-1.pl
@@ -0,0 +1,203 @@
+#!perl
+
+################################################################################
+=comment
+
+Perl Weekly Challenge 344
+=========================
+
+TASK #1
+-------
+*Array Form Compute*
+
+Submitted by: Mohammad Sajid Anwar
+
+You are given an array of integers, @ints and an integer, $x.
+
+Write a script to add $x to the integer in the array-form.
+
+ The array form of an integer is a digit-by-digit representation stored as an
+ array, where the most significant digit is at the 0th index.
+
+Example 1
+
+ Input: @ints = (1, 2, 3, 4), $x = 12
+ Output: (1, 2, 4, 6)
+
+Example 2
+
+ Input: @ints = (2, 7, 4), $x = 181
+ Output: (4, 5, 5)
+
+Example 3
+
+ Input: @ints = (9, 9, 9), $x = 1
+ Output: (1, 0, 0, 0)
+
+Example 4
+
+ Input: @ints = (1, 0, 0, 0, 0), $x = 9999
+ Output: (1, 9, 9, 9, 9)
+
+Example 5
+
+ Input: @ints = (0), $x = 1000
+ Output: (1, 0, 0, 0)
+
+=cut
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2025 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=comment
+
+Assumptions
+----------
+1. The integers are all unsigned.
+2. An array-form representation should contain no leading (redundant) zeros.
+
+Interface
+---------
+1. If no command-line arguments are given, the test suite is run. Otherwise:
+2. A list of 2 or more unsigned integers is entered on the command-line. The
+ last of these is $x; the rest are single digits and make up @ints.
+
+=cut
+#===============================================================================
+
+use v5.38.2; # Enables strictures
+use warnings;
+use Const::Fast;
+use Test::More;
+
+const my $USAGE => <<END;
+Usage:
+ perl $0 [<ints> ...]
+ perl $0
+
+ [<ints> ...] A list of digits followed by an unsigned integer (\$x)
+END
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\nChallenge 344, Task #1: Array Form Compute (Perl)\n\n";
+}
+
+#===============================================================================
+MAIN:
+#===============================================================================
+{
+ my $argc = scalar @ARGV;
+
+ if ($argc == 0)
+ {
+ run_tests();
+ }
+ elsif ($argc == 1)
+ {
+ error( 'Expected 0 or 2+ command-line arguments, found 1' );
+ }
+ else
+ {
+ my @ints = @ARGV;
+ my $x = pop @ints;
+
+ for (@ints)
+ {
+ / ^ [0-9] $ /x or error( "$_ is not a valid digit" );
+ }
+
+ $x =~ / ^ [0-9]+ $ /x or error( '$x is not a valid integer' );
+
+ printf "Input: \@ints = (%s), \$x = %d\n", join( ', ', @ints ), $x;
+
+ my $sum = add_array_form( \@ints, $x );
+
+ printf "Output: (%s)\n", join ', ', @$sum;
+ }
+}
+
+#-------------------------------------------------------------------------------
+sub add_array_form
+#-------------------------------------------------------------------------------
+{
+ my ($ints, $x) = @_;
+ my $dim = max( scalar @$ints, length $x ) + 1;
+ my @x_ar = split //, $x;
+ my @sum = (0) x $dim;
+ my $carry = 0;
+
+ unshift @x_ar, 0 until scalar @x_ar == $dim;
+ unshift @$ints, 0 until scalar @$ints == $dim;
+
+ for my $i (reverse( 0 .. $#sum ))
+ {
+ my $sum = $ints->[$i] + $x_ar[$i] + $carry;
+ $sum[$i] = $sum % 10;
+ $carry = $sum / 10;
+ }
+
+ shift @sum while $sum[0] == 0 && scalar @sum > 1;
+
+ return \@sum;
+}
+
+#-------------------------------------------------------------------------------
+sub run_tests
+#-------------------------------------------------------------------------------
+{
+ print "Running the test suite\n";
+
+ while (my $line = <DATA>)
+ {
+ chomp $line;
+
+ my ($test_name, $ints_str, $x, $expd_str) = split / \| /x, $line;
+
+ for ($test_name, $ints_str, $x, $expd_str)
+ {
+ s/ ^ \s+ //x;
+ s/ \s+ $ //x;
+ }
+
+ my @ints = split / \s+ /x, $ints_str;
+ my $sum = add_array_form( \@ints, $x );
+ my @expd = split / \s+ /x, $expd_str;
+
+ is_deeply $sum, \@expd, $test_name;
+ }
+
+ done_testing;
+}
+
+#-------------------------------------------------------------------------------
+sub error
+#-------------------------------------------------------------------------------
+{
+ my ($message) = @_;
+
+ die "ERROR: $message\n$USAGE";
+}
+
+#-------------------------------------------------------------------------------
+sub max
+#-------------------------------------------------------------------------------
+{
+ my ($lhs, $rhs) = @_;
+
+ return $lhs > $rhs ? $lhs : $rhs;
+}
+
+################################################################################
+
+__DATA__
+Example 1|1 2 3 4 | 12|1 2 4 6
+Example 2|2 7 4 | 181|4 5 5
+Example 3|9 9 9 | 1|1 0 0 0
+Example 4|1 0 0 0 0|9999|1 9 9 9 9
+Example 5|0 |1000|1 0 0 0
diff --git a/challenge-344/athanasius/perl/ch-2.pl b/challenge-344/athanasius/perl/ch-2.pl
new file mode 100644
index 0000000000..3d397af053
--- /dev/null
+++ b/challenge-344/athanasius/perl/ch-2.pl
@@ -0,0 +1,265 @@
+#!perl
+
+################################################################################
+=comment
+
+Perl Weekly Challenge 344
+=========================
+
+TASK #2
+-------
+*Array Formation*
+
+Submitted by: Mohammad Sajid Anwar
+
+You are given two list: @source and @target.
+
+Write a script to see if you can build the exact @target by putting these
+smaller lists from @source together in some order. You cannot break apart or
+change the order inside any of the smaller lists in @source.
+
+Example 1
+
+ Input: @source = ([2,3], [1], [4])
+ @target = (1, 2, 3, 4)
+ Output: true
+
+ Use in the order: [1], [2,3], [4]
+
+Example 2
+
+ Input: @source = ([1,3], [2,4])
+ @target = (1, 2, 3, 4)
+ Output: false
+
+Example 3
+
+ Input: @source = ([9,1], [5,8], [2])
+ @target = (5, 8, 2, 9, 1)
+ Output: true
+
+ Use in the order: [5,8], [2], [9,1]
+
+Example 4
+
+ Input: @source = ([1], [3])
+ @target = (1, 2, 3)
+ Output: false
+
+ Missing number: 2
+
+Example 5
+
+ Input: @source = ([7,4,6])
+ @target = (7, 4, 6)
+ Output: true
+
+ Use in the order: [7, 4, 6]
+
+=cut
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2025 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=comment
+
+Assumptions
+-----------
+1. The elements of @source and @target may be any strings.
+2. It must be possible to construct the target using elements from the source,
+ but there may be elements of @source which are not used in building @target.
+
+Interface
+---------
+1. If no command-line arguments are given, the test suite is run. Otherwise:
+2. Two strings are entered on the command-line. The first (the source) comprises
+ a non-empty list of non-empty, square-bracket-delimited lists of strings,
+ e.g., "[2,3], [1], [4]". The second (the target) comprises a non-empty list
+ of strings, e.g., "1, 2, 3, 4". List elements are separated by commas and/or
+ whitespace.
+
+=cut
+#===============================================================================
+
+use v5.38.2; # Enables strictures
+use warnings;
+use Const::Fast;
+use Test::More;
+
+const my $USAGE => <<END;
+Usage:
+ perl $0 <source> <target>
+ perl $0
+
+ <source> Non-empty list of bracket-delimited lists of strings
+ <target> Non-empty list of strings
+END
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\nChallenge 344, Task #2: Array Formation (Perl)\n\n";
+}
+
+#===============================================================================
+MAIN:
+#===============================================================================
+{
+ my $argc = scalar @ARGV;
+
+ if ($argc == 0)
+ {
+ run_tests();
+ }
+ elsif ($argc == 2)
+ {
+ my ($source, $target) = parse_input( @ARGV );
+
+ printf "Input: \@source = (%s)\n",
+ join ', ', map { '[' . join( ',', @$_ ) . ']' } @$source;
+
+ printf " \@target = (%s)\n", join ', ', @$target;
+
+ my $formation = find_array_formation( $source, $target );
+
+ if (scalar @$formation == 0)
+ {
+ print "Output: false\n";
+ }
+ else
+ {
+ printf "Output: true\n\nUse in the order: %s\n",
+ join ', ', map { '[' . join( ',', @$_ ) . ']' } @$formation;
+ }
+ }
+ else
+ {
+ error( "Expected 0 or 2 command-line arguments, found $argc" );
+ }
+}
+
+#-------------------------------------------------------------------------------
+sub find_array_formation
+#-------------------------------------------------------------------------------
+{
+ my ($source, $target) = @_;
+ my @source_strs = map { join '', @$_ } @$source;
+ my $target_str = join '', @$target;
+ my @formation = ();
+ my @indices = ();
+
+ if (recursive_search( \@source_strs, $target_str, \@indices ))
+ {
+ push @formation, $source->[$_] for @indices;
+ }
+
+ return \@formation;
+}
+
+#-------------------------------------------------------------------------------
+sub recursive_search
+#-------------------------------------------------------------------------------
+{
+ my ($source, $target, $indices) = @_;
+
+ return 1 if $target eq '';
+
+ for my $i (0 .. $#$source)
+ {
+ my $src = $source->[$i];
+ next unless defined $src;
+
+ if ($target =~ / ^ $src .* /x)
+ {
+ my $new_target = substr $target, length $src;
+ my @new_source = @$source;
+ $new_source[$i] = undef;
+
+ if (recursive_search( \@new_source, $new_target, $indices ))
+ {
+ unshift @$indices, $i;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+#-------------------------------------------------------------------------------
+sub parse_input
+#-------------------------------------------------------------------------------
+{
+ my ($source_str, $target_str) = @_;
+
+ # Note: characters not contained within square brackets are silently ignored
+
+ my @source = map { [ split / [\s,]+ /x ] } $source_str =~ / \[ (.*?) \] /gx;
+
+ scalar @source > 0 or error( 'The source list is empty' );
+
+ for my $src (@source)
+ {
+ scalar @$src > 0 or error( 'Empty source list element' );
+ }
+
+ my @target = split / [\s,]+ /x, $target_str;
+
+ scalar @target > 0 or error( 'The target list is empty' );
+
+ return \@source, \@target;
+}
+
+#-------------------------------------------------------------------------------
+sub run_tests
+#-------------------------------------------------------------------------------
+{
+ print "Running the test suite\n";
+
+ while (my $line = <DATA>)
+ {
+ chomp $line;
+
+ my ($test_name, $source_str, $target_str, $expected_str) =
+ split / \| /x, $line;
+
+ for ($test_name, $source_str, $target_str, $expected_str)
+ {
+ s/ ^ \s+ //x;
+ s/ \s+ $ //x;
+ }
+
+ my ($source, $target) = parse_input( $source_str, $target_str );
+ my $formation = find_array_formation( $source, $target );
+ my @expected = map { [ split /[\s,]+/ ] }
+ $expected_str =~ / \[ (.+?) \] /gx;
+
+ is_deeply $formation, \@expected, $test_name;
+ }
+
+ done_testing;
+}
+
+#-------------------------------------------------------------------------------
+sub error
+#-------------------------------------------------------------------------------
+{
+ my ($message) = @_;
+
+ die "ERROR: $message\n$USAGE";
+}
+
+################################################################################
+
+__DATA__
+Example 1|[2 3] [1] [4] |1 2 3 4 |[1] [2 3] [4]
+Example 2|[1 3] [2 4] |1 2 3 4 |
+Example 3|[9 1] [5 8] [2] |5 8 2 9 1|[5 8] [2] [9 1]
+Example 4|[1] [3] |1 2 3 |
+Example 5|[7 4 6] |7 4 6 |[7 4 6]
+Surplus |[2] [x y z] [9 1] [5 2] [5 8] [jk]|5 8 2 9 1|[5 8] [2] [9 1]
diff --git a/challenge-344/athanasius/raku/ch-1.raku b/challenge-344/athanasius/raku/ch-1.raku
new file mode 100644
index 0000000000..8450e2b04a
--- /dev/null
+++ b/challenge-344/athanasius/raku/ch-1.raku
@@ -0,0 +1,196 @@
+use v6d;
+
+################################################################################
+=begin comment
+
+Perl Weekly Challenge 344
+=========================
+
+TASK #1
+-------
+*Array Form Compute*
+
+Submitted by: Mohammad Sajid Anwar
+
+You are given an array of integers, @ints and an integer, $x.
+
+Write a script to add $x to the integer in the array-form.
+
+ The array form of an integer is a digit-by-digit representation stored as an
+ array, where the most significant digit is at the 0th index.
+
+Example 1
+
+ Input: @ints = (1, 2, 3, 4), $x = 12
+ Output: (1, 2, 4, 6)
+
+Example 2
+
+ Input: @ints = (2, 7, 4), $x = 181
+ Output: (4, 5, 5)
+
+Example 3
+
+ Input: @ints = (9, 9, 9), $x = 1
+ Output: (1, 0, 0, 0)
+
+Example 4
+
+ Input: @ints = (1, 0, 0, 0, 0), $x = 9999
+ Output: (1, 9, 9, 9, 9)
+
+Example 5
+
+ Input: @ints = (0), $x = 1000
+ Output: (1, 0, 0, 0)
+
+=end comment
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2025 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=begin comment
+
+Assumptions
+----------
+1. The integers are all unsigned.
+2. An array-form representation should contain no leading (redundant) zeros.
+
+Interface
+---------
+1. If no command-line arguments are given, the test suite is run. Otherwise:
+2. A list of 2 or more unsigned integers is entered on the command-line. The
+ last of these is $x; the rest are single digits and make up @ints.
+
+=end comment
+#===============================================================================
+
+use Test;
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ "\nChallenge 344, Task #1: Array Form Compute (Raku)\n".put;
+}
+
+#===============================================================================
+multi sub MAIN
+(
+ #| A list of digits followed by an unsigned integer ($x)
+
+ *@ints where { .elems >= 2 && .all ~~ UInt:D }
+)
+#===============================================================================
+{
+ my UInt $x = @ints.pop + 0; # Normalize
+
+ for @ints
+ {
+ / ^ <[ 0..9 ]> $ / or error( "$_ is not a valid digit" );
+ }
+
+ "Input: \@ints = (%s), \$x = %d\n".printf: @ints.join( ', ' ), $x;
+
+ my UInt @sum = add-array-form( @ints, $x );
+
+ "Output: (%s)\n".printf: @sum.join: ', ';
+}
+
+#===============================================================================
+multi sub MAIN() # No input: run the test suite
+#===============================================================================
+{
+ run-tests();
+}
+
+#-------------------------------------------------------------------------------
+sub add-array-form( List:D[UInt:D] $ints, UInt:D $x --> List:D[UInt:D] )
+#-------------------------------------------------------------------------------
+{
+ my UInt $dim = ($ints.elems, $x.chars).max + 1;
+ my UInt @x-ar = $x.split( '', :skip-empty ).map: { .Int };
+ my UInt @sum = 0 xx $dim;
+ my UInt $carry = 0;
+
+ @x-ar.unshift: 0 until @x-ar.elems == $dim;
+ $ints.unshift: 0 until $ints.elems == $dim;
+
+ for (0 .. @sum.end).reverse -> UInt $i
+ {
+ my UInt $sum = $ints[$i] + @x-ar[$i] + $carry;
+
+ @sum[$i] = $sum mod 10;
+ $carry = $sum div 10;
+ }
+
+ @sum.shift while @sum[0] == 0 && @sum.elems > 1;
+
+ return @sum;
+}
+
+#-------------------------------------------------------------------------------
+sub run-tests()
+#-------------------------------------------------------------------------------
+{
+ 'Running the test suite'.put;
+
+ for test-data.lines -> Str $line
+ {
+ my Str ($test-name, $ints-str, $x-str, $expd-str) = $line.split: / \| /;
+
+ for $test-name, $ints-str, $x-str, $expd-str
+ {
+ s/ ^ \s+ //;
+ s/ \s+ $ //;
+ }
+
+ my UInt @ints = $ints-str.split( / \s+ /, :skip-empty ).map: { .Int };
+ my UInt @sum = add-array-form( @ints, $x-str.Int );
+ my UInt @expd = $expd-str.split( / \s+ /, :skip-empty ).map: { .Int };
+
+ is-deeply @sum, @expd, $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|1 2 3 4 | 12|1 2 4 6
+ Example 2|2 7 4 | 181|4 5 5
+ Example 3|9 9 9 | 1|1 0 0 0
+ Example 4|1 0 0 0 0|9999|1 9 9 9 9
+ Example 5|0 |1000|1 0 0 0
+ END
+}
+
+################################################################################
diff --git a/challenge-344/athanasius/raku/ch-2.raku b/challenge-344/athanasius/raku/ch-2.raku
new file mode 100644
index 0000000000..315a853695
--- /dev/null
+++ b/challenge-344/athanasius/raku/ch-2.raku
@@ -0,0 +1,289 @@
+use v6d;
+
+################################################################################
+=begin comment
+
+Perl Weekly Challenge 344
+=========================
+
+TASK #2
+-------
+*Array Formation*
+
+Submitted by: Mohammad Sajid Anwar
+
+You are given two list: @source and @target.
+
+Write a script to see if you can build the exact @target by putting these
+smaller lists from @source together in some order. You cannot break apart or
+change the order inside any of the smaller lists in @source.
+
+Example 1
+
+ Input: @source = ([2,3], [1], [4])
+ @target = (1, 2, 3, 4)
+ Output: true
+
+ Use in the order: [1], [2,3], [4]
+
+Example 2
+
+ Input: @source = ([1,3], [2,4])
+ @target = (1, 2, 3, 4)
+ Output: false
+
+Example 3
+
+ Input: @source = ([9,1], [5,8], [2])
+ @target = (5, 8, 2, 9, 1)
+ Output: true
+
+ Use in the order: [5,8], [2], [9,1]
+
+Example 4
+
+ Input: @source = ([1], [3])
+ @target = (1, 2, 3)
+ Output: false
+
+ Missing number: 2
+
+Example 5
+
+ Input: @source = ([7,4,6])
+ @target = (7, 4, 6)
+ Output: true
+
+ Use in the order: [7, 4, 6]
+
+=end comment
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2025 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=begin comment
+
+Assumptions
+-----------
+1. The elements of @source and @target may be any strings.
+2. It must be possible to construct the target using elements from the source,
+ but there may be elements of @source which are not used in building @target.
+
+Interface
+---------
+1. If no command-line arguments are given, the test suite is run. Otherwise:
+2. Two strings are entered on the command-line. The first (the source) comprises
+ a non-empty list of non-empty, square-bracket-delimited lists of strings,
+ e.g., "[2,3], [1], [4]". The second (the target) comprises a non-empty list
+ of strings, e.g., "1, 2, 3, 4". List elements are separated by commas and/or
+ whitespace.
+
+=end comment
+#===============================================================================
+
+use Test;
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ "\nChallenge 344, Task #2: Array Formation (Raku)\n".put;
+}
+
+#===============================================================================
+multi sub MAIN
+(
+ Str:D $source, #= Non-empty list of bracket-delimited lists of strings
+ Str:D $target #= Non-empty list of strings
+)
+#===============================================================================
+{
+ my (Array[Array[Str]] $source-array,
+ Array[Str] $target-array) = parse-input( $source, $target );
+
+ "Input: \@source = (%s)\n".printf:
+ $source-array.map( { '[' ~ join( ',', @$_ ) ~ ']' } ).join: ', ';
+
+ " \@target = (%s)\n".printf: $target-array.join: ', ';
+
+ my Array[Str] @formation = find-array-formation( $source-array,
+ $target-array );
+
+ if @formation.elems == 0
+ {
+ 'Output: false'.put;
+ }
+ else
+ {
+ "Output: true\n\nUse in the order: %s\n".printf:
+ @formation.map( { '[' ~ join( ',', @$_ ) ~ ']' } ).join: ', ';
+ }
+}
+
+#===============================================================================
+multi sub MAIN() # No input: run the test suite
+#===============================================================================
+{
+ run-tests();
+}
+
+#-------------------------------------------------------------------------------
+sub find-array-formation
+(
+ List:D[List:D[Str:D]] $source where { .elems > 0 && .all.elems > 0 },
+ List:D[Str:D] $target where { .elems > 0 }
+--> List:D[List:D[Str:D]]
+)
+#-------------------------------------------------------------------------------
+{
+ my Str @source-strs = $source.map: { join '', @$_ };
+ my Str $target-str = $target.join: '';
+ my Array[Str] @formation;
+ my UInt @indices;
+
+ if recursive-search( @source-strs, $target-str, @indices )
+ {
+ @formation.push: $source[$_] for @indices;
+ }
+
+ return @formation;
+}
+
+#-------------------------------------------------------------------------------
+sub recursive-search
+(
+ List:D[Str:D] $source,
+ Str:D $target,
+ List:D[UInt:D] $indices
+--> Bool:D
+)
+#-------------------------------------------------------------------------------
+{
+ return True if $target eq '';
+
+ for 0 .. $source.end -> UInt $i
+ {
+ my Str $src = $source[$i];
+
+ next unless $src.defined;
+
+ if $target ~~ / ^ $src .* /
+ {
+ my Str $new-target = $target.substr: $src.chars;
+ my Str @new-source = $source.clone;
+ @new-source[$i] = Nil;
+
+ if recursive-search( @new-source, $new-target, $indices )
+ {
+ $indices.unshift: $i;
+
+ return True;
+ }
+ }
+ }
+
+ return False;
+}
+
+#-------------------------------------------------------------------------------
+sub parse-input( Str:D $source-str, Str:D $target-str --> List:D )
+#-------------------------------------------------------------------------------
+{
+ # Note: characters not contained within square brackets are silently ignored
+
+ my Array[Str] @source;
+ my Match @matches = $source-str ~~ m:g/ \[ (.*?) \] /;
+
+ for @matches -> Match $match
+ {
+ @source.push: Array[Str].new: (~$match[0]).split: / <[ \s , ]>+ /;
+ }
+
+ @source.elems > 0 or error( 'The source list is empty' );
+
+ for @source -> Array[Str] $src
+ {
+ $src.elems > 0 or error( 'Empty source list element' );
+ }
+
+ my Str @target = $target-str.split: / <[ \s , ]>+ /;
+
+ @target.elems > 0 or error( 'The target list is empty' );
+
+ return @source, @target;
+}
+
+#-------------------------------------------------------------------------------
+sub run-tests()
+#-------------------------------------------------------------------------------
+{
+ 'Running the test suite'.put;
+
+ for test-data.lines -> Str $line
+ {
+ my Str ($test-name, $source-str, $target-str, $expected-str) =
+ $line.split: / \| /;
+
+ for $test-name, $source-str, $target-str, $expected-str
+ {
+ s/ ^ \s+ //;
+ s/ \s+ $ //;
+ }
+
+ my (Array[Array[Str]] $source, Array[Str] $target) =
+ parse-input( $source-str, $target-str );
+ my Array[Str] @formation = find-array-formation( $source, $target );
+ my Array[Str] @expected;
+ my Match @matches = $expected-str ~~ m:g/ \[ (.*?) \] /;
+
+ for @matches -> Match $match
+ {
+ @expected.push: Array[Str].new: (~$match[0]).split: / <[ \s , ]>+ /;
+ }
+
+ is-deeply @formation, @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 3] [1] [4] |1 2 3 4 |[1] [2 3] [4]
+ Example 2|[1 3] [2 4] |1 2 3 4 |
+ Example 3|[9 1] [5 8] [2] |5 8 2 9 1|[5 8] [2] [9 1]
+ Example 4|[1] [3] |1 2 3 |
+ Example 5|[7 4 6] |7 4 6 |[7 4 6]
+ Surplus |[2] [x y z] [9 1] [5 2] [5 8] [jk]|5 8 2 9 1|[5 8] [2] [9 1]
+ END
+}
+
+################################################################################