aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-248/athanasius/perl/ch-1.pl199
-rw-r--r--challenge-248/athanasius/perl/ch-2.pl251
-rw-r--r--challenge-248/athanasius/raku/ch-1.raku202
-rw-r--r--challenge-248/athanasius/raku/ch-2.raku260
-rw-r--r--challenge-248/barroff/perl/ch-1.pl40
-rw-r--r--challenge-248/barroff/raku/ch-1.p634
-rw-r--r--challenge-248/bruce-gray/raku/ch-1.raku104
-rw-r--r--challenge-248/bruce-gray/raku/ch-2.raku26
-rw-r--r--challenge-248/cheok-yin-fung/perl/ch-1.pl30
-rw-r--r--challenge-248/cheok-yin-fung/perl/ch-2.pl42
-rw-r--r--challenge-248/roger-bell-west/blog.txt1
11 files changed, 1189 insertions, 0 deletions
diff --git a/challenge-248/athanasius/perl/ch-1.pl b/challenge-248/athanasius/perl/ch-1.pl
new file mode 100644
index 0000000000..18ce5983e7
--- /dev/null
+++ b/challenge-248/athanasius/perl/ch-1.pl
@@ -0,0 +1,199 @@
+#!perl
+
+################################################################################
+=comment
+
+Perl Weekly Challenge 248
+=========================
+
+TASK #1
+-------
+*Shortest Distance*
+
+Submitted by: Mohammad S Anwar
+
+You are given a string and a character in the given string.
+
+Write a script to return an array of integers of size same as length of the
+given string such that:
+
+ distance[i] is the distance from index i to the closest occurence of
+ the given character in the given string.
+
+ The distance between two indices i and j is abs(i - j).
+
+Example 1
+
+ Input: $str = "loveleetcode", $char = "e"
+ Output: (3,2,1,0,1,0,0,1,2,2,1,0)
+
+ The character 'e' appears at indices 3, 5, 6, and 11 (0-indexed).
+ The closest occurrence of 'e' for index 0 is at index 3, so the distance is
+ abs(0 - 3) = 3.
+ The closest occurrence of 'e' for index 1 is at index 3, so the distance is
+ abs(1 - 3) = 2.
+ For index 4, there is a tie between the 'e' at index 3 and the 'e' at index 5,
+ but the distance is still the same: abs(4 - 3) == abs(4 - 5) = 1.
+ The closest occurrence of 'e' for index 8 is at index 6, so the distance is
+ abs(8 - 6) = 2.
+
+Example 2
+
+ Input: $str = "aaab", $char = "b"
+ Output: (3,2,1,0)
+
+=cut
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2023 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=comment
+
+Interface
+---------
+If no command-line arguments are given, the test suite is run.
+
+Algorithm
+---------
+1. Create an array @min_dist of shortest distances, initially all empty.
+2. Assign 0 to each element of @min_dist corresponding to the target character.
+3. Assign 1 to each *empty* element of @min_dist that is immediately adjacent to
+ an element containing 0.
+4. Assign 2 to each *empty* element of @min_dist that is immediately adjacent to
+ an element containing 1.
+5. Repeat for 3, 4, 5, ... until no elements of @min_dist are empty.
+
+Note: this algorithm does not require any measurement of distances
+
+=cut
+#===============================================================================
+
+use v5.32.1; # Enables strictures
+use warnings;
+use Const::Fast;
+use List::Util qw( all min );
+use Test::More;
+
+const my $USAGE =>
+"Usage:
+ perl $0 <str> <char>
+ perl $0
+
+ <str> A string of one or more characters
+ <char> A character in the given string\n";
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\nChallenge 248, Task #1: Shortest Distance (Perl)\n\n";
+}
+
+#===============================================================================
+MAIN:
+#===============================================================================
+{
+ my $argc = scalar @ARGV;
+
+ if ($argc == 0)
+ {
+ run_tests();
+ }
+ elsif ($argc == 2)
+ {
+ my ($str, $char) = @ARGV;
+
+ $str =~ /$char/ or error( qq[The given character "$char" does not ] .
+ 'appear in the given string' );
+
+ print qq[Input: \$str = "$str", \$char = "$char"\n];
+
+ my ($min_dist) = find_shortest_distances( $str, $char );
+
+ printf "Output: (%s)\n", join ',', @$min_dist;
+ }
+ else
+ {
+ error( "Expected 0 or 2 command-line arguments, found $argc" );
+ }
+}
+
+#-------------------------------------------------------------------------------
+sub find_shortest_distances
+#-------------------------------------------------------------------------------
+{
+ my ($str, $char) = @_;
+ my @str_char = split //, $str;
+ my @min_dist = (undef) x scalar @str_char;
+
+ for my $i (0 .. $#str_char)
+ {
+ $min_dist[ $i ] = 0 if $str_char[ $i ] eq $char;
+ }
+
+ my $target = 0;
+
+ until (all { defined $_ } @min_dist)
+ {
+ for my $i (0 .. $#str_char)
+ {
+ next unless defined $min_dist[ $i ] && $target == $min_dist[ $i ];
+
+ $min_dist[ $i - 1 ] = $target + 1
+ if $i > 0 && !defined $min_dist[ $i - 1 ];
+
+ $min_dist[ $i + 1 ] = $target + 1
+ if $i < $#str_char && !defined $min_dist[ $i + 1 ];
+ }
+
+ ++$target;
+ }
+
+ return \@min_dist;
+}
+
+#-------------------------------------------------------------------------------
+sub run_tests
+#-------------------------------------------------------------------------------
+{
+ print "Running the test suite\n";
+
+ while (my $line = <DATA>)
+ {
+ chomp $line;
+
+ my ($test_name, $str, $char, $exp_str) = split / \| /x, $line;
+
+ for ($test_name, $str, $char, $exp_str)
+ {
+ s/ ^ \s+ //x;
+ s/ \s+ $ //x;
+ }
+
+ my ($sd) = find_shortest_distances( $str, $char );
+ my @exp = split / \s+ /x, $exp_str;
+
+ is_deeply $sd, \@exp, $test_name;
+ }
+
+ done_testing;
+}
+
+#-------------------------------------------------------------------------------
+sub error
+#-------------------------------------------------------------------------------
+{
+ my ($message) = @_;
+
+ die "ERROR: $message\n$USAGE";
+}
+
+################################################################################
+
+__DATA__
+Example 1|loveleetcode|e|3 2 1 0 1 0 0 1 2 2 1 0
+Example 2|aaab |b|3 2 1 0
diff --git a/challenge-248/athanasius/perl/ch-2.pl b/challenge-248/athanasius/perl/ch-2.pl
new file mode 100644
index 0000000000..71f5743167
--- /dev/null
+++ b/challenge-248/athanasius/perl/ch-2.pl
@@ -0,0 +1,251 @@
+#!perl
+
+################################################################################
+=comment
+
+Perl Weekly Challenge 248
+=========================
+
+TASK #2
+-------
+*Submatrix Sum*
+
+Submitted by: Jorg Sommrey
+
+You are given a NxM matrix A of integers.
+
+Write a script to construct a (N-1)x(M-1) matrix B having elements that are the
+sum over the 2x2 submatrices of A,
+
+ b[i,k] = a[i,k] + a[i,k+1] + a[i+1,k] + a[i+1,k+1]
+
+Example 1
+
+ Input: $a = [
+ [1, 2, 3, 4],
+ [5, 6, 7, 8],
+ [9, 10, 11, 12]
+ ]
+
+ Output: $b = [
+ [14, 18, 22],
+ [30, 34, 38]
+ ]
+
+Example 2
+
+ Input: $a = [
+ [1, 0, 0, 0],
+ [0, 1, 0, 0],
+ [0, 0, 1, 0],
+ [0, 0, 0, 1]
+ ]
+
+ Output: $b = [
+ [2, 1, 0],
+ [1, 2, 1],
+ [0, 1, 2]
+ ]
+
+=cut
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2023 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=comment
+
+Interface
+---------
+If no command-line arguments are given, the test suite is run.
+
+=cut
+#===============================================================================
+
+use v5.32.1; # Enables strictures
+use warnings;
+use Const::Fast;
+use Regexp::Common qw( number );
+use Test::More;
+
+const my $USAGE =>
+"Usage:
+ perl $0 [<a> ...]
+ perl $0
+
+ [<a> ...] An N x M matrix of integers (N, M >= 2)\n";
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\nChallenge 248, Task #2: Submatrix Sum (Perl)\n\n";
+}
+
+#===============================================================================
+MAIN:
+#===============================================================================
+{
+ if (scalar @ARGV == 0)
+ {
+ run_tests();
+ }
+ else
+ {
+ my $matrix_a = parse_matrix( \@ARGV );
+
+ print_matrix( 'Input: $a = ', $matrix_a );
+
+ my $matrix_b = submatrix_sum( $matrix_a );
+
+ print "\n";
+ print_matrix( 'Output: $b = ', $matrix_b );
+ }
+}
+
+#-------------------------------------------------------------------------------
+sub submatrix_sum
+#-------------------------------------------------------------------------------
+{
+ my ($matrix_a) = @_;
+ my @matrix_b;
+
+ for my $i (0 .. $#$matrix_a - 1)
+ {
+ for my $k (0 .. $#{ $matrix_a->[ 0 ] } - 1)
+ {
+ # b[i,k] = a[i,k] + a[i,k+1] + a[i+1,k] + a[i+1,k+1]
+
+ $matrix_b[ $i ][ $k ] = $matrix_a->[ $i ][ $k ] +
+ $matrix_a->[ $i ][ $k + 1 ] +
+ $matrix_a->[ $i + 1 ][ $k ] +
+ $matrix_a->[ $i + 1 ][ $k + 1 ];
+ }
+ }
+
+ return \@matrix_b;
+}
+
+#-------------------------------------------------------------------------------
+sub parse_matrix
+#-------------------------------------------------------------------------------
+{
+ my ($a) = @_;
+ my (@matrix, $num_cols);
+
+ for my $row_str (@$a)
+ {
+ my @row;
+
+ for my $elem (grep { / \S /x } split / \s+ /x, $row_str)
+ {
+ if ($elem =~ / ^ $RE{num}{int} $ /x)
+ {
+ push @row, $elem;
+ }
+ else
+ {
+ error( qq[Element "$elem" is not a valid integer] );
+ }
+ }
+
+ push @matrix, \@row;
+
+ if (defined $num_cols)
+ {
+ scalar @row == $num_cols
+ or error( 'The input matrix is not rectangular' );
+ }
+ else
+ {
+ $num_cols = scalar @row;
+ $num_cols >= 2 or error( 'M is too small' );
+ }
+ }
+
+ return \@matrix;
+}
+
+#-------------------------------------------------------------------------------
+sub print_matrix
+#-------------------------------------------------------------------------------
+{
+ my ($prefix, $matrix) = @_;
+ my $tab = ' ' x length $prefix;
+ my @width = (1) x scalar @{ $matrix->[ 0 ] };
+
+ for my $row (@$matrix)
+ {
+ for my $i (0 .. $#$row)
+ {
+ my $w = length $row->[ $i ];
+
+ $width[ $i ] = $w if $w > $width[ $i ];
+ }
+ }
+
+ print "$prefix\[\n";
+
+ for my $row (@$matrix)
+ {
+ my @row_str;
+
+ for my $i (0 .. $#$row)
+ {
+ push @row_str, sprintf '%*d', $width[ $i ], $row->[ $i ];
+ }
+
+ printf "%s [%s]\n", $tab, join ', ', @row_str;
+ }
+
+ print "$tab]\n";
+}
+
+#-------------------------------------------------------------------------------
+sub run_tests
+#-------------------------------------------------------------------------------
+{
+ print "Running the test suite\n";
+
+ while (my $line = <DATA>)
+ {
+ chomp $line;
+
+ my ($test_name, $matrix_str, $expected_str) = split / \| /x, $line;
+
+ for ($test_name, $matrix_str, $expected_str)
+ {
+ s/ ^ \s+ //x;
+ s/ \s+ $ //x;
+ }
+
+ my @a = split / \; /x, $matrix_str;
+ my @b = split / \; /x, $expected_str;
+
+ my $matrix_a = parse_matrix( \@a );
+ my $expected = parse_matrix( \@b );
+ my $matrix_b = submatrix_sum( $matrix_a );
+
+ is_deeply $matrix_b, $expected, $test_name;
+ }
+
+ done_testing;
+}
+
+#-------------------------------------------------------------------------------
+sub error
+#-------------------------------------------------------------------------------
+{
+ my ($message) = @_;
+
+ die "ERROR: $message\n$USAGE";
+}
+
+################################################################################
+
+__DATA__
+Example 1|1 2 3 4; 5 6 7 8; 9 10 11 12|14 18 22; 30 34 38
+Example 2|1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 1|2 1 0; 1 2 1; 0 1 2
diff --git a/challenge-248/athanasius/raku/ch-1.raku b/challenge-248/athanasius/raku/ch-1.raku
new file mode 100644
index 0000000000..4dc6c89aa3
--- /dev/null
+++ b/challenge-248/athanasius/raku/ch-1.raku
@@ -0,0 +1,202 @@
+use v6d;
+
+################################################################################
+=begin comment
+
+Perl Weekly Challenge 248
+=========================
+
+TASK #1
+-------
+*Shortest Distance*
+
+Submitted by: Mohammad S Anwar
+
+You are given a string and a character in the given string.
+
+Write a script to return an array of integers of size same as length of the
+given string such that:
+
+ distance[i] is the distance from index i to the closest occurence of
+ the given character in the given string.
+
+ The distance between two indices i and j is abs(i - j).
+
+Example 1
+
+ Input: $str = "loveleetcode", $char = "e"
+ Output: (3,2,1,0,1,0,0,1,2,2,1,0)
+
+ The character 'e' appears at indices 3, 5, 6, and 11 (0-indexed).
+ The closest occurrence of 'e' for index 0 is at index 3, so the distance is
+ abs(0 - 3) = 3.
+ The closest occurrence of 'e' for index 1 is at index 3, so the distance is
+ abs(1 - 3) = 2.
+ For index 4, there is a tie between the 'e' at index 3 and the 'e' at index 5,
+ but the distance is still the same: abs(4 - 3) == abs(4 - 5) = 1.
+ The closest occurrence of 'e' for index 8 is at index 6, so the distance is
+ abs(8 - 6) = 2.
+
+Example 2
+
+ Input: $str = "aaab", $char = "b"
+ Output: (3,2,1,0)
+
+=end comment
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2023 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=begin comment
+
+Interface
+---------
+If no command-line arguments are given, the test suite is run.
+
+Algorithm
+---------
+1. Create an array @min-dist of shortest distances, initially all empty.
+2. Assign 0 to each element of @min-dist corresponding to the target character.
+3. Assign 1 to each *empty* element of @min-dist that is immediately adjacent to
+ an element containing 0.
+4. Assign 2 to each *empty* element of @min-dist that is immediately adjacent to
+ an element containing 1.
+5. Repeat for 3, 4, 5, ... until no elements of @min-dist are empty.
+
+Note: this algorithm does not require any measurement of distances.
+
+=end comment
+#===============================================================================
+
+use Test;
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ "\nChallenge 248, Task #1: Shortest Distance (Raku)\n".put;
+}
+
+#===============================================================================
+multi sub MAIN
+(
+ Str:D $str where { .chars >= 1 }, #= A string of one or more characters
+ Str:D $char where { .chars == 1 && $str ~~ / $char / }
+ #= A character in the given string
+)
+#===============================================================================
+{
+ qq[Input: \$str = "$str", \$char = "$char"].put;
+
+ my UInt @min-dist = find-shortest-distances( $str, $char );
+
+ "Output: (%s)\n".printf: @min-dist.join: ',';
+}
+
+#===============================================================================
+multi sub MAIN() # No input: run the test suite
+#===============================================================================
+{
+ run-tests();
+}
+
+#-------------------------------------------------------------------------------
+sub find-shortest-distances
+(
+ Str:D $str where { .chars >= 1 }, #= A string of one or more characters
+ Str:D $char where { .chars == 1 && $str ~~ / $char / }
+ #= A character in the given string
+--> List:D[UInt:D]
+)
+#-------------------------------------------------------------------------------
+{
+ my Str @str-char = $str.split: '', :skip-empty;
+ my UInt @min-dist = Int xx @str-char.elems;
+
+ for 0 .. @str-char.end -> UInt $i
+ {
+ @min-dist[ $i ] = 0 if @str-char[ $i ] eq $char;
+ }
+
+ my UInt $target = 0;
+
+ until @min-dist.all.defined
+ {
+ for 0 .. @str-char.end -> UInt $i
+ {
+ next unless @min-dist[ $i ].defined && $target == @min-dist[ $i ];
+
+ @min-dist[ $i - 1 ] = $target + 1
+ if $i > 0 && !@min-dist[ $i - 1 ].defined;
+
+ @min-dist[ $i + 1 ] = $target + 1
+ if $i < @str-char.end && !@min-dist[ $i + 1 ].defined;
+ }
+
+ ++$target;
+ }
+
+ return @min-dist;
+}
+
+#-------------------------------------------------------------------------------
+sub run-tests()
+#-------------------------------------------------------------------------------
+{
+ 'Running the test suite'.put;
+
+ for test-data.lines -> Str $line
+ {
+ my Str ($test-name, $str, $char, $expected-str) = $line.split: / \| /;
+
+ for $test-name, $str, $char, $expected-str
+ {
+ s/ ^ \s+ //;
+ s/ \s+ $ //;
+ }
+
+ my UInt @min-dist = find-shortest-distances( $str, $char );
+ my UInt @expected = $expected-str.split( / \s+ / ).map: { .Int };
+
+ is-deeply @min-dist, @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|loveleetcode|e|3 2 1 0 1 0 0 1 2 2 1 0
+ Example 2|aaab |b|3 2 1 0
+ END
+}
+
+################################################################################
diff --git a/challenge-248/athanasius/raku/ch-2.raku b/challenge-248/athanasius/raku/ch-2.raku
new file mode 100644
index 0000000000..94651468a7
--- /dev/null
+++ b/challenge-248/athanasius/raku/ch-2.raku
@@ -0,0 +1,260 @@
+use v6d;
+
+################################################################################
+=begin comment
+
+Perl Weekly Challenge 248
+=========================
+
+TASK #2
+-------
+*Submatrix Sum*
+
+Submitted by: Jorg Sommrey
+
+You are given a NxM matrix A of integers.
+
+Write a script to construct a (N-1)x(M-1) matrix B having elements that are the
+sum over the 2x2 submatrices of A,
+
+ b[i,k] = a[i,k] + a[i,k+1] + a[i+1,k] + a[i+1,k+1]
+
+Example 1
+
+ Input: $a = [
+ [1, 2, 3, 4],
+ [5, 6, 7, 8],
+ [9, 10, 11, 12]
+ ]
+
+ Output: $b = [
+ [14, 18, 22],
+ [30, 34, 38]
+ ]
+
+Example 2
+
+ Input: $a = [
+ [1, 0, 0, 0],
+ [0, 1, 0, 0],
+ [0, 0, 1, 0],
+ [0, 0, 0, 1]
+ ]
+
+ Output: $b = [
+ [2, 1, 0],
+ [1, 2, 1],
+ [0, 1, 2]
+ ]
+
+=end comment
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2023 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=begin comment
+
+Interface
+---------
+If no command-line arguments are given, the test suite is run.
+
+=end comment
+#===============================================================================
+
+use Test;
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ "\nChallenge 248, Task #2: Submatrix Sum (Raku)\n".put;
+}
+
+#===============================================================================
+multi sub MAIN
+(
+ #| An N x M matrix of integers (N, M >= 2)
+
+ *@a where { .all ~~ Str:D && .elems >= 2 }
+)
+#===============================================================================
+{
+ my Array[Array[Int]] $matrix-a = parse-matrix( @a );
+
+ print-matrix( 'Input: $a = ', $matrix-a );
+
+ my Array[Array[Int]] $matrix-b = submatrix-sum( $matrix-a );
+
+ put();
+ print-matrix( 'Output: $b = ', $matrix-b );
+}
+
+#===============================================================================
+multi sub MAIN() # No input: run the test suite
+#===============================================================================
+{
+ run-tests();
+}
+
+#-------------------------------------------------------------------------------
+sub submatrix-sum( List:D[List:D[Int:D]] $matrix-a --> List:D[List:D[Int:D]] )
+#-------------------------------------------------------------------------------
+{
+ my Array[Int] @matrix-b;
+
+ for 0 .. $matrix-a.end - 1 -> UInt $i
+ {
+ @matrix-b[ $i ] = Array[Int].new;
+
+ for 0 .. $matrix-a[ 0 ].end - 1 -> UInt $k
+ {
+ # b[i,k] = a[i,k] + a[i,k+1] + a[i+1,k] + a[i+1,k+1]
+
+ @matrix-b[ $i; $k ] = $matrix-a[ $i; $k ] +
+ $matrix-a[ $i; $k + 1 ] +
+ $matrix-a[ $i + 1; $k ] +
+ $matrix-a[ $i + 1; $k + 1 ];
+ }
+ }
+
+ return @matrix-b;
+}
+
+#-------------------------------------------------------------------------------
+sub parse-matrix( List:D[Str:D] $a --> List:D[List:D[Int:D]] )
+#-------------------------------------------------------------------------------
+{
+ my Array[Int] @matrix;
+ my UInt $num-cols;
+
+ for @$a -> Str $row-str
+ {
+ my Int @row;
+
+ for $row-str.split( / \s+ /, :skip-empty ) -> Str $elem
+ {
+ if +$elem ~~ Int:D
+ {
+ @row.push: +$elem;
+ }
+ else
+ {
+ error( qq[Element "$elem" is not a valid integer] );
+ }
+ }
+
+ @matrix.push: @row;
+
+ if $num-cols.defined
+ {
+ @row.elems == $num-cols
+ or error( 'The input matrix is not rectangular' );
+ }
+ else
+ {
+ ($num-cols = @row.elems) >= 2 or error( 'M is too small' );
+ }
+ }
+
+ return @matrix;
+}
+
+#-------------------------------------------------------------------------------
+sub print-matrix( Str:D $prefix, List:D[List:D[Int:D]] $matrix )
+#-------------------------------------------------------------------------------
+{
+ my Str $tab = ' ' x $prefix.chars;
+ my UInt @width = 1 xx $matrix[ 0 ].elems;
+
+ for @$matrix -> Int @row
+ {
+ for 0 .. @row.end -> UInt $i
+ {
+ my UInt $w = @row[ $i ].chars;
+
+ @width[ $i ] = $w if $w > @width[ $i ];
+ }
+ }
+
+ "$prefix\[".put;
+
+ for @$matrix -> Int @row
+ {
+ my Str @row-str;
+
+ for 0 .. @row.end -> UInt $i
+ {
+ @row-str.push: '%*d'.sprintf: @width[ $i ], @row[ $i ];
+ }
+
+ "%s [%s]\n".printf: $tab, @row-str.join: ', ';
+ }
+
+ "$tab]".put;
+}
+
+#-------------------------------------------------------------------------------
+sub run-tests()
+#-------------------------------------------------------------------------------
+{
+ 'Running the test suite'.put;
+
+ for test-data.lines -> Str $line
+ {
+ my Str ($test-name, $matrix-str, $expected-str) = $line.split: / \| /;
+
+ for $test-name, $matrix-str, $expected-str
+ {
+ s/ ^ \s+ //;
+ s/ \s+ $ //;
+ }
+
+ my Str @a = $matrix-str\ .split: / \; /;
+ my Str @b = $expected-str.split: / \; /;
+
+ my Array[Array[Int]] $matrix-a = parse-matrix( @a );
+ my Array[Array[Int]] $expected = parse-matrix( @b );
+ my Array[Array[Int]] $matrix-b = submatrix-sum( $matrix-a );
+
+ is-deeply $matrix-b, $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|1 2 3 4; 5 6 7 8; 9 10 11 12|14 18 22; 30 34 38
+ Example 2|1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 1|2 1 0; 1 2 1; 0 1 2
+ END
+}
+
+################################################################################
diff --git a/challenge-248/barroff/perl/ch-1.pl b/challenge-248/barroff/perl/ch-1.pl
new file mode 100644
index 0000000000..b9868b1df6
--- /dev/null
+++ b/challenge-248/barroff/perl/ch-1.pl
@@ -0,0 +1,40 @@
+#!/usr/bin/env perl
+
+use v5.38;
+
+sub minimal_distance ( $start, @positions ) {
+ use List::Util qw / min /;
+ min( map( { abs( $start - $_ ) } @positions ) );
+}
+
+sub shortest_distance ( $str, $char ) {
+ my @split_str = split( //, $str );
+ my %indices;
+ $indices{$_}++ for grep( { $split_str[$_] eq $char } 0 .. $#split_str );
+ return () unless %indices;
+ my @result =
+ map( { exists $indices{$_} ? 0 : minimal_distance( $_, keys %indices ) }
+ 0 .. $#split_str );
+ return \@result;
+}
+
+sub MAIN() {
+ if (@ARGV) {
+
+ #| Run on command line argument
+ say shortest_distance( $ARGV[0], @ARGV[ 1 .. -1 ] );
+ }
+ else {
+ #| Run test cases
+ use Test2::V0 qw( is plan );
+ plan 2;
+
+ is shortest_distance( 'loveleetcode', 'e' ),
+ [ 3, 2, 1, 0, 1, 0, 0, 1, 2, 2, 1, 0 ],
+ "works for ('loveleetcode', 'e')";
+ is shortest_distance( 'aaab', 'b' ), [ 3, 2, 1, 0 ],
+ "works for ('aaab', 'b')";
+ }
+}
+
+MAIN();
diff --git a/challenge-248/barroff/raku/ch-1.p6 b/challenge-248/barroff/raku/ch-1.p6
new file mode 100644
index 0000000000..2d741d95dd
--- /dev/null
+++ b/challenge-248/barroff/raku/ch-1.p6
@@ -0,0 +1,34 @@
+#!/usr/bin/env raku
+
+use v6.d;
+
+sub minimal-distance(Int:D $start, @positions --> Int:D) {
+ min(map({ abs($start - $_) }, @positions));
+}
+
+sub sd(Str:D $str, Str:D $char where $char.chars == 1 --> List) {
+ my @indices = $str.indices($char);
+ # return empty list if string does not contain searched character
+ return () unless @indices;
+ map({ $_ (elem) @indices
+ ?? 0 # index is character
+ !! minimal-distance($_, @indices) # find closest index
+ }, 0..$str.chars - 1
+ ).list;
+}
+
+#| Run test cases
+multi sub MAIN('test') {
+ use Test;
+ plan 2;
+
+ is sd('loveleetcode', 'e'), [3,2,1,0,1,0,0,1,2,2,1,0],
+ 'works for "e" in "loveleetcode"';
+ is sd('aaab', 'b'), [3, 2, 1, 0],
+ 'works for "b" in "aaab"';
+}
+
+#| Take user provided list like aba aabb abcd bac aabc
+multi sub MAIN(Str:D $str, Str:D $char) {
+ say sd($str, $char);
+}
diff --git a/challenge-248/bruce-gray/raku/ch-1.raku b/challenge-248/bruce-gray/raku/ch-1.raku
new file mode 100644
index 0000000000..7077ef3fec
--- /dev/null
+++ b/challenge-248/bruce-gray/raku/ch-1.raku
@@ -0,0 +1,104 @@
+# Distance from nearest Left, from nearest Right, minimum of the two.
+# O(3N), but something about it is slowing it down.
+sub task1_three_linear_scans ( Str $letter, Str $s ) {
+ my @sc = $s.comb;
+
+ my $distance; # Used for side effects within two .map()'s.
+ my &f = { $distance = 0 if $_ eq $letter; $distance++ };
+
+ $distance = Inf; my @L = @sc.map(&f);
+ $distance = Inf; my @R = @sc.reverse.map(&f).reverse;
+
+ return @L »min« @R;
+}
+
+# Lots of participants used variations of this algorithm.
+# It is potentially a poor performer, O(N²)?, depending on the
+# number of times the letter occurs; 1K string with
+# 10% $letter would be 100K comparisons.
+multi sub infix:<absdiff> (\a, \b) { ( a - b ).abs }
+sub task1_compare_to_all ( Str $letter, Str $s ) {
+ my @pos = $s.indices($letter);
+
+ return map { [min] $_ «absdiff« @pos }, ^$s.chars;
+}
+
+# More intricate, but could be wildly more efficient.
+# Directly generates the whole result in a continuous single Seq.
+sub task1_pyramid ( Str $letter, Str $s ) {
+ # Except for the head&tail, distances always form a pyramid,
+ # either flat-top (1 2 3 4 4 3 2 1) or pointy (1 2 3 4 3 2 1).
+ sub pyramid ( (Int $z1, Int $z2) ) {
+ my $n = $z2 - $z1 - 1;
+ my $m = $n div 2;
+ my @c = 1 .. $m;
+ return |0, |@c, |($m + 1 if $n !%% 2), |@c.reverse;
+ }
+
+ my @pos = $s.indices($letter)
+ or return Inf xx $s.chars;
+
+ # Looks faster, but that big last flatten kills performance,
+ # and limits us to 65K array.
+ # return map |*,
+ # (1..@pos.head).reverse,
+ # |@pos.rotor(2 => -1).map(&pyramid),
+ # 0, (1 .. ($s.chars - @pos.tail - 1));
+
+ return gather {
+ .take for reverse 1..@pos.head;
+ .take for |@pos.rotor(2 => -1).map({ |.&pyramid });
+ .take for 0 .. ($s.chars - @pos.tail - 1);
+ }
+}
+
+
+constant $hamlet = 'What a piece of work is a man! how noble in reason! how infinite in faculties! in form and moving how express and admirable! in action how like an angel! in apprehension how like a god! the beauty of the world, the paragon of animals!';
+constant @tests =
+ ( 'e', 'loveleetcode' , [3,2,1,0,1,0,0,1,2,2,1,0] ),
+ ( 'b', 'aaab' , [3,2,1,0] ),
+
+ ( 'c', 'aaab' , [Inf xx 4] ),
+
+ # Extra tests from mark-anderson
+ ( 'e', 'eabcde' ,