aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad Sajid Anwar <Mohammad.Anwar@yahoo.com>2025-05-04 13:30:49 +0100
committerGitHub <noreply@github.com>2025-05-04 13:30:49 +0100
commit84bcb0e007d3a41c9fb4e12e841f4379d1cad826 (patch)
tree78cff1f29f325180546f2557f3c8abed7d8357d7
parenteef2ec3748987e5d70e61e0813211844c2913cc6 (diff)
parentb01bb307259cb5de0d13b956b74d3138d135882c (diff)
downloadperlweeklychallenge-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.pl172
-rw-r--r--challenge-319/athanasius/perl/ch-2.pl194
-rw-r--r--challenge-319/athanasius/raku/ch-1.raku164
-rw-r--r--challenge-319/athanasius/raku/ch-2.raku193
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
+}
+
+################################################################################