From 939fffbc1b487b5cad792159b5cc829dcef4c630 Mon Sep 17 00:00:00 2001 From: PerlMonk Athanasius Date: Fri, 14 Aug 2020 04:41:57 -0700 Subject: Perl & Raku solutions to Tasks 1 & 2 of the Perl Weekly Challenge #073 On branch branch-for-challenge-073 Changes to be committed: new file: challenge-073/athanasius/perl/ch-1.pl new file: challenge-073/athanasius/perl/ch-2.pl new file: challenge-073/athanasius/raku/ch-1.raku new file: challenge-073/athanasius/raku/ch-2.raku --- challenge-073/athanasius/perl/ch-1.pl | 106 +++++++++++++++++++++++ challenge-073/athanasius/perl/ch-2.pl | 145 ++++++++++++++++++++++++++++++++ challenge-073/athanasius/raku/ch-1.raku | 78 +++++++++++++++++ challenge-073/athanasius/raku/ch-2.raku | 131 +++++++++++++++++++++++++++++ 4 files changed, 460 insertions(+) create mode 100644 challenge-073/athanasius/perl/ch-1.pl create mode 100644 challenge-073/athanasius/perl/ch-2.pl create mode 100644 challenge-073/athanasius/raku/ch-1.raku create mode 100644 challenge-073/athanasius/raku/ch-2.raku diff --git a/challenge-073/athanasius/perl/ch-1.pl b/challenge-073/athanasius/perl/ch-1.pl new file mode 100644 index 0000000000..0fb9a24dcf --- /dev/null +++ b/challenge-073/athanasius/perl/ch-1.pl @@ -0,0 +1,106 @@ +#!perl + +################################################################################ +=comment + +Perl Weekly Challenge 073 +========================= + +Task #1 +------- +*Min Sliding Window* + +Submitted by: Mohammad S Anwar + +You are given an array of integers @A and sliding window size $S. + +Write a script to create an array of min from each sliding window. + +Example + +Input: @A = (1, 5, 0, 2, 9, 3, 7, 6, 4, 8) and $S = 3 +Output: (0, 0, 0, 2, 3, 3, 4, 4) + +[(1 5 0) 2 9 3 7 6 4 8] = Min (0) +[1 (5 0 2) 9 3 7 6 4 8] = Min (0) +[1 5 (0 2 9) 3 7 6 4 8] = Min (0) +[1 5 0 (2 9 3) 7 6 4 8] = Min (2) +[1 5 0 2 (9 3 7) 6 4 8] = Min (3) +[1 5 0 2 9 (3 7 6) 4 8] = Min (3) +[1 5 0 2 9 3 (7 6 4) 8] = Min (4) +[1 5 0 2 9 3 7 (6 4 8)] = Min (4) + +=cut +################################################################################ + +#--------------------------------------# +# Copyright © 2020 PerlMonk Athanasius # +#--------------------------------------# + +use strict; +use warnings; +use Const::Fast; # Exports const() +use Getopt::Long; # Exports GetOptions() +use List::Util qw( min ); +use PerlX::Window; # Exports window() and @window +use Regexp::Common qw( number ); # Exports %RE{num} + +const my $USAGE => +"Usage: + perl $0 [-S ] [-A +] + + -S Sliding window size: 0 < S <= integers in A + -A + Sequence of one or more integers\n"; + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + $| = 1; + print "\nChallenge 073, Task #1: Min Sliding Window (Perl)\n\n"; +} + +#=============================================================================== +MAIN: +#=============================================================================== +{ + my ($S, @A) = parse_command_line(); + + printf "Input: \@A = (%s) and \$S = %d\n", join(', ', @A), $S; + + my @minima; + push @minima, min(@window) while window(@A, $S); + + printf "Output: (%s)\n", join(', ', @minima); +} + +#------------------------------------------------------------------------------- +sub parse_command_line +#------------------------------------------------------------------------------- +{ + my ($S, @A); + + GetOptions + ( + 'S=i' => \$S, + 'A=i{1,}' => \@A, + ) or die $USAGE; + + scalar @ARGV == 0 or die $USAGE; + is_int($S) && $S > 0 or die $USAGE; + is_int($_) or die $USAGE for @A; + $S <= scalar @A or die $USAGE; + + return ($S, @A); +} + +#------------------------------------------------------------------------------- +sub is_int +#------------------------------------------------------------------------------- +{ + my ($n) = @_; + + return defined($n) && $n =~ / \A $RE{num}{int} \z /x; +} + +################################################################################ diff --git a/challenge-073/athanasius/perl/ch-2.pl b/challenge-073/athanasius/perl/ch-2.pl new file mode 100644 index 0000000000..a62a6dec8e --- /dev/null +++ b/challenge-073/athanasius/perl/ch-2.pl @@ -0,0 +1,145 @@ +#!perl + +################################################################################ +=comment + +Perl Weekly Challenge 073 +========================= + +Task #2 +------- +*Smallest Neighbour* + +Submitted by: Mohammad S Anwar + +You are given an array of integers @A. + +Write a script to create an array that represents the smaller element to the +left of each corresponding index. If none found then use 0. + +Example 1 + +Input: @A = (7, 8, 3, 12, 10) +Output: (0, 7, 0, 3, 3) + +For index 0, the smallest number to the left of $A[0] i.e. 7 is none, so we put +0. +For index 1, the smallest number to the left of $A[1] as compare to 8, in (7) is +7 so we put 7. +For index 2, the smallest number to the left of $A[2] as compare to 3, in (7, 8) +is none, so we put 0. +For index 3, the smallest number to the left of $A[3] as compare to 12, in (7, +8, 3) is 3, so we put 3. +For index 4, the smallest number to the left of $A[4] as compare to 10, in (7, +8, 3, 12) is 3, so we put 3 again. + +Example 2 + +Input: @A = (4, 6, 5) +Output: (0, 4, 4) + +For index 0, the smallest number to the left of $A[0] is none, so we put 0. +For index 1, the smallest number to the left of $A[1] as compare to 6, in (4) is +4, so we put 4. +For index 2, the smallest number to the left of $A[2] as compare to 5, in (4, 6) +is 4, so we put 4 again. + +=cut +################################################################################ + +#--------------------------------------# +# Copyright © 2020 PerlMonk Athanasius # +#--------------------------------------# + +use strict; +use warnings; +use Const::Fast; # Exports const() +use Regexp::Common qw( number ); # Exports %RE + +const my $USAGE => +"Usage: + perl $0 [ ...] + + [ ...] Sequence of one or more integers\n"; + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + $| = 1; + print "\nChallenge 073, Task #2: Smallest Neighbour (Perl)\n\n"; +} + +#=============================================================================== +MAIN: +#=============================================================================== +{ + my @A = parse_command_line(); + my @out = (0); # The first element has no left-hand neighbours + # and so is always 0 + my $min = $A[0]; # In the loop below, $min contains the smallest + # of the elements with index 0 .. $i-1 + + # For each element $A[$i] after the first: record the minimum of the ele- + # ments with index 0..$i-1 IFF that minimum is less than $A[$i]; otherwise, + # record 0 + + for my $i (1 .. $#A) + { + my $current = $A[$i]; + + push @out, $min < $current ? $min : 0; + + $min = $current if $current < $min; # Update $min for next iteration + } + + print_arrays(\@A, \@out); +} + +#------------------------------------------------------------------------------- +sub parse_command_line +#------------------------------------------------------------------------------- +{ + scalar @ARGV > 0 or die $USAGE; + + / \A $RE{num}{int} \z /x or die $USAGE for @ARGV; + + return @ARGV; +} + +#------------------------------------------------------------------------------- +sub print_arrays +#------------------------------------------------------------------------------- +{ + my ($input, $output) = @_; + my @widths; + + # Calculate the print width for each element to facilitate vertical align- + # ment of corresponding elements in the input and output sequences + + for my $i (0 .. $#$input) + { + my $len_in = length $input ->[$i]; + my $len_out = length $output->[$i]; + + push @widths, $len_in > $len_out ? $len_in : $len_out; + } + + # Print the input and output sequences + + for my $args (['Input: @A =', $input ], + ['Output:', $output]) + { + my $array = $args->[1]; + + printf "%-11s (%s)\n", + $args->[0], + join ', ', map + { + sprintf '%*d', $widths[$_], $array->[$_] + + } 0 .. $#$array; + } +} + +################################################################################ diff --git a/challenge-073/athanasius/raku/ch-1.raku b/challenge-073/athanasius/raku/ch-1.raku new file mode 100644 index 0000000000..52526279a3 --- /dev/null +++ b/challenge-073/athanasius/raku/ch-1.raku @@ -0,0 +1,78 @@ +use v6d; + +################################################################################ +=begin comment + +Perl Weekly Challenge 073 +========================= + +Task #1 +------- +*Min Sliding Window* + +Submitted by: Mohammad S Anwar + +You are given an array of integers @A and sliding window size $S. + +Write a script to create an array of min from each sliding window. + +Example + +Input: @A = (1, 5, 0, 2, 9, 3, 7, 6, 4, 8) and $S = 3 +Output: (0, 0, 0, 2, 3, 3, 4, 4) + +[(1 5 0) 2 9 3 7 6 4 8] = Min (0) +[1 (5 0 2) 9 3 7 6 4 8] = Min (0) +[1 5 (0 2 9) 3 7 6 4 8] = Min (0) +[1 5 0 (2 9 3) 7 6 4 8] = Min (2) +[1 5 0 2 (9 3 7) 6 4 8] = Min (3) +[1 5 0 2 9 (3 7 6) 4 8] = Min (3) +[1 5 0 2 9 3 (7 6 4) 8] = Min (4) +[1 5 0 2 9 3 7 (6 4 8)] = Min (4) + +=end comment +################################################################################ + +#--------------------------------------# +# Copyright © 2020 PerlMonk Athanasius # +#--------------------------------------# + +subset Natural of UInt where * > 0; + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + "\nChallenge 073, Task #1: Min Sliding Window (Raku)\n".put; +} + +#=============================================================================== +sub MAIN +( + Natural:D :$S, #= Sliding window size: 0 < S <= integers in A + + *@A where { @A.elems > 0 && #= Sequence of one or more integers + @A.elems >= $S && + @A.all ~~ Int:D } +) +#=============================================================================== +{ + "Input: @A = (%s) and \$S = %d\n".printf: @A.join(', '), $S; + + my Int @minima; + @minima.push: min @A[$_ .. $_ + $S - 1] for 0 .. @A.elems - $S; + + "Output: (%s)\n".printf: @minima.join: ', '; +} + +#------------------------------------------------------------------------------- +sub USAGE() +#------------------------------------------------------------------------------- +{ + my Str $usage = $*USAGE; + + $usage ~~ s/ ($*PROGRAM-NAME) /raku $0/; + $usage.put; +} + +################################################################################ diff --git a/challenge-073/athanasius/raku/ch-2.raku b/challenge-073/athanasius/raku/ch-2.raku new file mode 100644 index 0000000000..df2f74d872 --- /dev/null +++ b/challenge-073/athanasius/raku/ch-2.raku @@ -0,0 +1,131 @@ +use v6d; + +################################################################################ +=begin comment + +Perl Weekly Challenge 073 +========================= + +Task #2 +------- +*Smallest Neighbour* + +Submitted by: Mohammad S Anwar + +You are given an array of integers @A. + +Write a script to create an array that represents the smaller element to the +left of each corresponding index. If none found then use 0. + +Example 1 + +Input: @A = (7, 8, 3, 12, 10) +Output: (0, 7, 0, 3, 3) + +For index 0, the smallest number to the left of $A[0] i.e. 7 is none, so we put +0. +For index 1, the smallest number to the left of $A[1] as compare to 8, in (7) is +7 so we put 7. +For index 2, the smallest number to the left of $A[2] as compare to 3, in (7, 8) +is none, so we put 0. +For index 3, the smallest number to the left of $A[3] as compare to 12, in (7, +8, 3) is 3, so we put 3. +For index 4, the smallest number to the left of $A[4] as compare to 10, in (7, +8, 3, 12) is 3, so we put 3 again. + +Example 2 + +Input: @A = (4, 6, 5) +Output: (0, 4, 4) + +For index 0, the smallest number to the left of $A[0] is none, so we put 0. +For index 1, the smallest number to the left of $A[1] as compare to 6, in (4) is +4, so we put 4. +For index 2, the smallest number to the left of $A[2] as compare to 5, in (4, 6) +is 4, so we put 4 again. + +=end comment +################################################################################ + +#--------------------------------------# +# Copyright © 2020 PerlMonk Athanasius # +#--------------------------------------# + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + "\nChallenge 073, Task #2: Smallest Neighbour (Raku)\n".put; +} + +#=============================================================================== +sub MAIN +( + *@A where { @A.elems > 0 && #= Sequence of one or more integers + @A.all ~~ Int:D } +) +#=============================================================================== +{ + my Int @out = (0); # The first element has no left-hand neighbours + # and so is always 0 + my Int $min = @A[0]; # In the loop below, $min contains the smallest + # of the elements with index 0 .. $i-1 + + # For each element @A[$i] after the first: record the minimum of the ele- + # ments with index 0..$i-1 IFF that minimum is less than @A[$i]; otherwise, + # record 0 + + for 1 .. @A.end -> UInt $i + { + my Int $current = @A[$i]; + + @out.push: $min < $current ?? $min !! 0; + + $min = $current if $current < $min; # Update $min for next iteration + } + + print-arrays(@A, @out); +} + +#------------------------------------------------------------------------------- +sub USAGE() +#------------------------------------------------------------------------------- +{ + my Str $usage = $*USAGE; + + $usage ~~ s/ ($*PROGRAM-NAME) /raku $0/; + $usage.put; +} + +#------------------------------------------------------------------------------- +sub print-arrays(Array:D[Int:D] $input, Array:D[Int:D] $output) +#------------------------------------------------------------------------------- +{ + my UInt @widths; + + # Calculate the print width for each element to facilitate vertical align- + # ment of corresponding elements in the input and output sequences + + for 0 .. $input.end -> UInt $i + { + my $len_in = $input[$i].chars; + my $len_out = $output[$i].chars; + + @widths.push: $len_in > $len_out ?? $len_in !! $len_out; + } + + # Print the input and output sequences + + for ['Input: @A =', $input ], + ['Output:', $output] -> @args + { + my @array = @args[1].list; + + "%-11s (%s)\n".printf: + @args[0], + (0 .. @array.end).map( { '%*d'.sprintf: @widths[$_], @array[$_] } ) + .join: ', '; + } +} + +################################################################################ -- cgit