diff options
| -rw-r--r-- | challenge-248/athanasius/perl/ch-1.pl | 199 | ||||
| -rw-r--r-- | challenge-248/athanasius/perl/ch-2.pl | 251 | ||||
| -rw-r--r-- | challenge-248/athanasius/raku/ch-1.raku | 202 | ||||
| -rw-r--r-- | challenge-248/athanasius/raku/ch-2.raku | 260 | ||||
| -rw-r--r-- | challenge-248/barroff/perl/ch-1.pl | 40 | ||||
| -rw-r--r-- | challenge-248/barroff/raku/ch-1.p6 | 34 | ||||
| -rw-r--r-- | challenge-248/bruce-gray/raku/ch-1.raku | 104 | ||||
| -rw-r--r-- | challenge-248/bruce-gray/raku/ch-2.raku | 26 | ||||
| -rw-r--r-- | challenge-248/cheok-yin-fung/perl/ch-1.pl | 30 | ||||
| -rw-r--r-- | challenge-248/cheok-yin-fung/perl/ch-2.pl | 42 | ||||
| -rw-r--r-- | challenge-248/roger-bell-west/blog.txt | 1 |
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' , |
