diff options
| author | Mohammad Sajid Anwar <Mohammad.Anwar@yahoo.com> | 2025-05-04 13:30:49 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-04 13:30:49 +0100 |
| commit | 84bcb0e007d3a41c9fb4e12e841f4379d1cad826 (patch) | |
| tree | 78cff1f29f325180546f2557f3c8abed7d8357d7 | |
| parent | eef2ec3748987e5d70e61e0813211844c2913cc6 (diff) | |
| parent | b01bb307259cb5de0d13b956b74d3138d135882c (diff) | |
| download | perlweeklychallenge-club-84bcb0e007d3a41c9fb4e12e841f4379d1cad826.tar.gz perlweeklychallenge-club-84bcb0e007d3a41c9fb4e12e841f4379d1cad826.tar.bz2 perlweeklychallenge-club-84bcb0e007d3a41c9fb4e12e841f4379d1cad826.zip | |
Merge pull request #11968 from PerlMonk-Athanasius/branch-for-challenge-319
Perl & Raku solutions to Tasks 1 & 2 for Week 319
| -rw-r--r-- | challenge-319/athanasius/perl/ch-1.pl | 172 | ||||
| -rw-r--r-- | challenge-319/athanasius/perl/ch-2.pl | 194 | ||||
| -rw-r--r-- | challenge-319/athanasius/raku/ch-1.raku | 164 | ||||
| -rw-r--r-- | challenge-319/athanasius/raku/ch-2.raku | 193 |
4 files changed, 723 insertions, 0 deletions
diff --git a/challenge-319/athanasius/perl/ch-1.pl b/challenge-319/athanasius/perl/ch-1.pl new file mode 100644 index 0000000000..462088a82e --- /dev/null +++ b/challenge-319/athanasius/perl/ch-1.pl @@ -0,0 +1,172 @@ +#!perl + +################################################################################ +=comment + +Perl Weekly Challenge 319 +========================= + +TASK #1 +------- +*Word Count* + +Submitted by: Mohammad Sajid Anwar + +You are given a list of words containing alphabetic characters only. + +Write a script to return the count of words either starting with a vowel or +ending with a vowel. + +Example 1 + + Input: @list = ("unicode", "xml", "raku", "perl") + Output: 2 + + The words are "unicode" and "raku". + +Example 2 + + Input: @list = ("the", "weekly", "challenge") + Output: 2 + +Example 3 + + Input: @list = ("perl", "python", "postgres") + Output: 0 + +=cut +################################################################################ + +#--------------------------------------# +# Copyright © 2025 PerlMonk Athanasius # +#--------------------------------------# + +#=============================================================================== +=comment + +Interface +--------- +1. If no command-line arguments are given, the test suite is run. Otherwise: +2. A non-empty list of words is entered on the command-line. + +Notes +----- +1. From Example 2, it appears that "y" is not considered a vowel, even when (as + there) it functions as one. +2. Vowels are specified in lowercase, and are assumed to have uppercase counter- + parts. +3. If support for non-English European languages is wanted, vowels with dia- + critics ("è", "é", "ê", etc.) may be added to the constant array @VOWELS. +4. Non-alphabetic chars in the input are silently ignored. + +=cut +#=============================================================================== + +use v5.32; # Enables strictures +use warnings; +use utf8; +use Const::Fast; +use Set::Scalar; +use Test::More; + +const my @VOWELS => qw( a e i o u ); +const my $VOWELS => Set::Scalar->new( @VOWELS ); +const my $USAGE => <<END; +Usage: + perl $0 <list> + perl $0 + + <list> A non-empty list of words +END + +my $vowels; + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + $| = 1; + print "\nChallenge 319, Task #1: Word Count (Perl)\n\n"; +} + +#=============================================================================== +MAIN: +#=============================================================================== +{ + if (scalar @ARGV == 0) + { + run_tests(); + } + else + { + my @list = @ARGV; + + printf "Input: \@list = (%s)\n", join ', ', map { qq["$_"] } @list; + + my $count = count_words( \@list ); + + print "Output: $count\n"; + } +} + +#------------------------------------------------------------------------------- +sub count_words +#------------------------------------------------------------------------------- +{ + my ($list) = @_; + my $count = 0; + + for my $word (@$list) + { + my $first = substr $word, 0, 1; + my $last = substr $word, -1; + + ++$count if $VOWELS->has( lc $first ) || $VOWELS->has( lc $last ); + } + + return $count; +} + +#------------------------------------------------------------------------------- +sub run_tests +#------------------------------------------------------------------------------- +{ + print "Running the test suite\n"; + + while (my $line = <DATA>) + { + chomp $line; + + my ($test_name, $list_str, $expected) = split / \| /x, $line; + + for ($test_name, $list_str, $expected) + { + s/ ^ \s+ //x; + s/ \s+ $ //x; + } + + my @list = split / \s+ /x, $list_str; + my $count = count_words( \@list ); + + is $count, $expected, $test_name; + } + + done_testing; +} + +#------------------------------------------------------------------------------- +sub error +#------------------------------------------------------------------------------- +{ + my ($message) = @_; + + die "ERROR: $message\n$USAGE"; +} + +################################################################################ + +__DATA__ +Example 1|unicode xml raku perl|2 +Example 2|the weekly challenge |2 +Example 3|perl python postgres |0 +Capitals |Unicode xml RAKU Perl|2 diff --git a/challenge-319/athanasius/perl/ch-2.pl b/challenge-319/athanasius/perl/ch-2.pl new file mode 100644 index 0000000000..b65dd83c3c --- /dev/null +++ b/challenge-319/athanasius/perl/ch-2.pl @@ -0,0 +1,194 @@ +#!perl + +################################################################################ +=comment + +Perl Weekly Challenge 319 +========================= + +TASK #2 +------- +*Minimum Common* + +Submitted by: Mohammad Sajid Anwar + +You are given two arrays of integers. + +Write a script to return the minimum integer common to both arrays. If none +found return -1. + +Example 1 + + Input: @array_1 = (1, 2, 3, 4) + @array_2 = (3, 4, 5, 6) + Output: 3 + + The common integer in both arrays: 3, 4 + The minimum is 3. + +Example 2 + + Input: @array_1 = (1, 2, 3) + @array_2 = (2, 4) + Output: 2 + +Example 3 + + Input: @array_1 = (1, 2, 3, 4) + @array_2 = (5, 6, 7, 8) + Output: -1 + +=cut +################################################################################ + +#--------------------------------------# +# Copyright © 2025 PerlMonk Athanasius # +#--------------------------------------# + +#=============================================================================== +=comment + +Assumption +---------- +Since -1 is returned on failure, it may be inferred that the input is limited to +*unsigned* integers. + +Interface +--------- +1. If no command-line arguments are given, the test suite is run. Otherwise: +2. Two strings are entered on the command-line. Each string contains a list of + whitespace-separated unsigned integers. + +=cut +#=============================================================================== + +use v5.32; # Enables strictures +use warnings; +use Const::Fast; +use List::Util qw( min ); +use Regexp::Common qw( number ); +use Set::Scalar; +use Test::More; + +const my $USAGE => <<END; +Usage: + perl $0 <array_1> <array_2> + perl $0 + + <array_1> First string of space-separated unsigned integers + <array_2> Second string of space-separated unsigned integers +END + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + $| = 1; + print "\nChallenge 319, Task #2: Minimum Common (Perl)\n\n"; +} + +#=============================================================================== +MAIN: +#=============================================================================== +{ + my $argc = scalar @ARGV; + + if ($argc == 0) + { + run_tests(); + } + elsif ($argc == 2) + { + my $array_1 = parse_array( $ARGV[ 0 ] ); + my $array_2 = parse_array( $ARGV[ 1 ] ); + + printf "Input: \@array_1 = (%s)\n", join ', ', @$array_1; + printf " \@array_2 = (%s)\n", join ', ', @$array_2; + + my $min_common = find_min_common( $array_1, $array_2 ); + + print "Output: $min_common\n"; + } + else + { + error( "Expected 0 or 2 command-line arguments, found $argc" ); + } +} + +#------------------------------------------------------------------------------- +sub find_min_common +#------------------------------------------------------------------------------- +{ + my ($array_1, $array_2) = @_; + my $set1 = Set::Scalar->new( @$array_1 ); + my $set2 = Set::Scalar->new( @$array_2 ); + my $common = $set1->intersection( $set2 ); + + return $common->is_empty ? -1 : min( $common->members ); +} + +#------------------------------------------------------------------------------- +sub parse_array +#------------------------------------------------------------------------------- +{ + my ($str) = @_; + my @elems = split / \s+ /x, $str; + my @array; + + for my $elem (@elems) + { + $elem =~ / ^ $RE{num}{int} $ /x + or error( qq["$elem" is not a valid integer] ); + + $elem >= 0 or error( "$elem is negative" ); + + push @array, $elem; + } + + return \@array; +} + +#------------------------------------------------------------------------------- +sub run_tests +#------------------------------------------------------------------------------- +{ + print "Running the test suite\n"; + + while (my $line = <DATA>) + { + chomp $line; + + my ($test_name, $array_1_str, $array_2_str, $expected) = + split / \| /x, $line; + + for ($test_name, $array_1_str, $array_2_str, $expected) + { + s/ ^ \s+ //x; + s/ \s+ $ //x; + } + + my $array_1 = parse_array( $array_1_str ); + my $array_2 = parse_array( $array_2_str ); + my $min_common = find_min_common( $array_1, $array_2 ); + + is $min_common, $expected, $test_name; + } + + done_testing; +} + +#------------------------------------------------------------------------------- +sub error +#------------------------------------------------------------------------------- +{ + my ($message) = @_; + + die "ERROR: $message\n$USAGE"; +} + +################################################################################ + +__DATA__ +Example 1|1 2 3 4|3 4 5 6| 3 +Example 2|1 2 3 |2 4 | 2 +Example 3|1 2 3 4|5 6 7 8|-1 diff --git a/challenge-319/athanasius/raku/ch-1.raku b/challenge-319/athanasius/raku/ch-1.raku new file mode 100644 index 0000000000..2d676e869d --- /dev/null +++ b/challenge-319/athanasius/raku/ch-1.raku @@ -0,0 +1,164 @@ +use v6d; + +################################################################################ +=begin comment + +Perl Weekly Challenge 319 +========================= + +TASK #1 +------- +*Word Count* + +Submitted by: Mohammad Sajid Anwar + +You are given a list of words containing alphabetic characters only. + +Write a script to return the count of words either starting with a vowel or +ending with a vowel. + +Example 1 + + Input: @list = ("unicode", "xml", "raku", "perl") + Output: 2 + + The words are "unicode" and "raku". + +Example 2 + + Input: @list = ("the", "weekly", "challenge") + Output: 2 + +Example 3 + + Input: @list = ("perl", "python", "postgres") + Output: 0 + +=end comment +################################################################################ + +#--------------------------------------# +# Copyright © 2025 PerlMonk Athanasius # +#--------------------------------------# + +#=============================================================================== +=begin comment + +Interface +--------- +1. If no command-line arguments are given, the test suite is run. Otherwise: +2. A non-empty list of words is entered on the command-line. + +Notes +----- +1. From Example 2, it appears that "y" is not considered a vowel, even when (as + there) it functions as one. +2. Vowels are specified in lowercase, and are assumed to have uppercase counter- + parts. +3. If support for non-English European languages is wanted, vowels with dia- + critics ("è", "é", "ê", etc.) may be added to $VOWELS. +4. Non-alphabetic chars in the input are silently ignored. + +=end comment +#=============================================================================== + +use Test; + +my Set $VOWELS = set < a e i o u >; + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + "\nChallenge 319, Task #1: Word Count (Raku)\n".put; +} + +#=============================================================================== +multi sub MAIN +( + #| A non-empty list of non-empty words + + *@list where { .elems > 0 && .all.chars > 0 } +) +#=============================================================================== +{ + "Input: \@list = (%s)\n".printf: @list.map( { qq["$_"] } ).join: ', '; + + my UInt $count = count-words( @list ); + + "Output: $count".put; +} + +#=============================================================================== +multi sub MAIN() # No input: run the test suite +#=============================================================================== +{ + run-tests(); +} + +#------------------------------------------------------------------------------- +sub count-words( List:D[Str:D] $list --> UInt:D ) +#------------------------------------------------------------------------------- +{ + my UInt $count = 0; + + for @$list -> Str $word + { + my Str $first = $word.substr: 0, 1; + my Str $last = $word.substr: *-1; + + ++$count if $first.lc ∈ $VOWELS || $last.lc ∈ $VOWELS; + } + + return $count; +} + +#------------------------------------------------------------------------------- +sub run-tests() +#------------------------------------------------------------------------------- +{ + 'Running the test suite'.put; + + for test-data.lines -> Str $line + { + my Str ($test-name, $list-str, $expected) = $line.split: / \| /; + + for $test-name, $list-str, $expected + { + s/ ^ \s+ //; + s/ \s+ $ //; + } + + my Str @list = $list-str.split: / \s+ /, :skip-empty; + my UInt $count = count-words( @list ); + + is $count, $expected.Int, $test-name; + } + + done-testing; +} + +#------------------------------------------------------------------------------- +sub USAGE() +#------------------------------------------------------------------------------- +{ + my Str $usage = $*USAGE; + + $usage ~~ s:g/ ($*PROGRAM-NAME) /raku $0/; + + $usage.put; +} + +#------------------------------------------------------------------------------- +sub test-data( --> Str:D ) +#------------------------------------------------------------------------------- +{ + return q:to/END/; + Example 1|unicode xml raku perl|2 + Example 2|the weekly challenge |2 + Example 3|perl python postgres |0 + Capitals |Unicode xml RAKU Perl|2 + END +} + +################################################################################ diff --git a/challenge-319/athanasius/raku/ch-2.raku b/challenge-319/athanasius/raku/ch-2.raku new file mode 100644 index 0000000000..d272765406 --- /dev/null +++ b/challenge-319/athanasius/raku/ch-2.raku @@ -0,0 +1,193 @@ +use v6d; + +################################################################################ +=begin comment + +Perl Weekly Challenge 319 +========================= + +TASK #2 +------- +*Minimum Common* + +Submitted by: Mohammad Sajid Anwar + +You are given two arrays of integers. + +Write a script to return the minimum integer common to both arrays. If none +found return -1. + +Example 1 + + Input: @array_1 = (1, 2, 3, 4) + @array_2 = (3, 4, 5, 6) + Output: 3 + + The common integer in both arrays: 3, 4 + The minimum is 3. + +Example 2 + + Input: @array_1 = (1, 2, 3) + @array_2 = (2, 4) + Output: 2 + +Example 3 + + Input: @array_1 = (1, 2, 3, 4) + @array_2 = (5, 6, 7, 8) + Output: -1 + +=end comment +################################################################################ + +#--------------------------------------# +# Copyright © 2025 PerlMonk Athanasius # +#--------------------------------------# + +#=============================================================================== +=begin comment + +Assumption +---------- +Since -1 is returned on failure, it may be inferred that the input is limited to +*unsigned* integers. + +Interface +--------- +1. If no command-line arguments are given, the test suite is run. Otherwise: +2. Two strings are entered on the command-line. Each string contains a list of + whitespace-separated unsigned integers. + +=end comment +#=============================================================================== + +use Test; + +#------------------------------------------------------------------------------- +BEGIN +#------------------------------------------------------------------------------- +{ + "\nChallenge 319, Task #2: Minimum Common (Raku)\n".put; +} + +#=============================================================================== +multi sub MAIN +( + Str:D $array_1, #= First string of space-separated unsigned integers + Str:D $array_2 #= Second string of space-separated unsigned integers +) +#=============================================================================== +{ + my UInt @array_1 = parse-array( $array_1 ); + my UInt @array_2 = parse-array( $array_2 ); + + "Input: \@array_1 = (%s)\n".printf: @array_1.join: ', '; + " \@array_2 = (%s)\n".printf: @array_2.join: ', '; + + my Int $min-common = find-min-common( @array_1, @array_2 ); + + "Output: $min-common".put; +} + +#=============================================================================== +multi sub MAIN() # No input: run the test suite +#=============================================================================== +{ + run-tests(); +} + +#------------------------------------------------------------------------------- +sub find-min-common +( + List:D[UInt:D] $array_1, + List:D[UInt:D] $array_2 +--> Int:D +) +#------------------------------------------------------------------------------- +{ + my Set[UInt] $set1 = Set[UInt].new: @$array_1; + my Set[UInt] $set2 = Set[UInt].new: @$array_2; + my Set[UInt] $common = $set1 ∩ $set2; + + return $common ≡ ∅ ?? -1 !! $common.keys.min; +} + +#------------------------------------------------------------------------------- +sub parse-array( Str:D $str --> List:D[UInt:D] ) +#------------------------------------------------------------------------------- +{ + my UInt @array; + my Str @elems = $str.split: / \s+ /, :skip-empty; + + for @elems -> Str $elem + { + +$elem ~~ UInt or error( qq["$elem" is not a valid unsigned integer] ); + + @array.push: +$elem; + } + + return @array; +} + +#------------------------------------------------------------------------------- +sub run-tests() +#------------------------------------------------------------------------------- +{ + 'Running the test suite'.put; + + for test-data.lines -> Str $line + { + my Str ($test-name, $array_1-str, $array_2-str, $expected) = + $line.split: / \| /; + + for $test-name, $array_1-str, $array_2-str, $expected + { + s/ ^ \s+ //; + s/ \s+ $ //; + } + + my UInt @array_1 = parse-array( $array_1-str ); + my UInt @array_2 = parse-array( $array_2-str ); + my Int $min-common = find-min-common( @array_1, @array_2 ); + + is $min-common, $expected.Int, $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|3 4 5 6| 3 + Example 2|1 2 3 |2 4 | 2 + Example 3|1 2 3 4|5 6 7 8|-1 + END +} + +################################################################################ |
