aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-265/athanasius/perl/ch-1.pl175
-rw-r--r--challenge-265/athanasius/perl/ch-2.pl237
-rw-r--r--challenge-265/athanasius/raku/ch-1.raku170
-rw-r--r--challenge-265/athanasius/raku/ch-2.raku212
4 files changed, 794 insertions, 0 deletions
diff --git a/challenge-265/athanasius/perl/ch-1.pl b/challenge-265/athanasius/perl/ch-1.pl
new file mode 100644
index 0000000000..da575aee89
--- /dev/null
+++ b/challenge-265/athanasius/perl/ch-1.pl
@@ -0,0 +1,175 @@
+#!perl
+
+################################################################################
+=comment
+
+Perl Weekly Challenge 265
+=========================
+
+TASK #1
+-------
+*33% Appearance*
+
+Submitted by: Mohammad Sajid Anwar
+
+You are given an array of integers, @ints.
+
+Write a script to find an integer in the given array that appeared 33% or more.
+If more than one found, return the smallest. If none found then return undef.
+
+Example 1
+
+ Input: @ints = (1,2,3,3,3,3,4,2)
+ Output: 3
+
+ 1 appeared 1 times.
+ 2 appeared 2 times.
+ 3 appeared 4 times.
+
+ 3 appeared 50% (>33%) in the given array.
+
+Example 2
+
+ Input: @ints = (1,1)
+ Output: 1
+
+ 1 appeared 2 times.
+
+ 1 appeared 100% (>33%) in the given array.
+
+Example 3
+
+ Input: @ints = (1,2,3)
+ Output: 1
+
+ 1 appeared 1 times.
+ 2 appeared 1 times.
+ 3 appeared 1 times.
+
+ Since all three appeared 33.3% (>33%) in the given array.
+ We pick the smallest of all.
+
+=cut
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2024 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=comment
+
+Interface
+---------
+1. If no command-line arguments are given, the test suite is run. Otherwise:
+2. A list of one or more integers is given on the command-line.
+
+=cut
+#===============================================================================
+
+use v5.32.1; # Enables strictures
+use warnings;
+use Const::Fast;
+use List::Util qw( min );
+use POSIX qw( ceil );
+use Regexp::Common qw( number );
+use Test::More;
+
+const my $THRESHOLD => 0.33;
+const my $USAGE => <<END;
+Usage:
+ perl $0 [<ints> ...]
+ perl $0
+
+ [<ints> ...] A non-empty list of integers
+END
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\nChallenge 265, Task #1: 33% Appearance (Perl)\n\n";
+}
+
+#===============================================================================
+MAIN:
+#===============================================================================
+{
+ if (scalar @ARGV == 0)
+ {
+ run_tests();
+ }
+ else
+ {
+ my @ints = @ARGV;
+
+ / ^ $RE{num}{int} $ /x or error( qq["$_" is not a valid integer] )
+ for @ints;
+
+ printf "Input: \@ints = (%s)\n", join ',', @ints;
+
+ my $solution = solve( \@ints );
+
+ printf "Output: %s\n", defined $solution ? $solution : 'undef (= none)';
+ }
+}
+
+#-------------------------------------------------------------------------------
+sub solve
+#-------------------------------------------------------------------------------
+{
+ my ($ints) = @_;
+ my $target = ceil( scalar( @$ints ) * $THRESHOLD );
+ my %count;
+ ++$count{ $_ } for @$ints;
+ my @candidates = grep { $count{ $_ } >= $target } keys %count;
+
+ return scalar @candidates > 0 ? min( @candidates ) : undef;
+}
+
+#-------------------------------------------------------------------------------
+sub run_tests
+#-------------------------------------------------------------------------------
+{
+ print "Running the test suite\n";
+
+ while (my $line = <DATA>)
+ {
+ chomp $line;
+
+ my ($test_name, $ints_str, $expected_str) = split / \| /x, $line;
+
+ for ($test_name, $ints_str, $expected_str)
+ {
+ s/ ^ \s+ //x;
+ s/ \s+ $ //x;
+ }
+
+ my @ints = split / \s+ /x, $ints_str;
+ my $solution = solve( \@ints );
+ my $expected = length $expected_str > 0 ? $expected_str : undef;
+
+ is $solution, $expected, $test_name;
+ }
+
+ done_testing;
+}
+
+#-------------------------------------------------------------------------------
+sub error
+#-------------------------------------------------------------------------------
+{
+ my ($message) = @_;
+
+ die "ERROR: $message\n$USAGE";
+}
+
+################################################################################
+
+__DATA__
+Example 1| 1 2 3 3 3 3 4 2| 3
+Example 2| 1 1 | 1
+Example 3| 1 2 3 | 1
+None | 1 2 3 4 |
+Negatives|-1 0 -2 1 -2 -1 |-2
diff --git a/challenge-265/athanasius/perl/ch-2.pl b/challenge-265/athanasius/perl/ch-2.pl
new file mode 100644
index 0000000000..f4624c8ed4
--- /dev/null
+++ b/challenge-265/athanasius/perl/ch-2.pl
@@ -0,0 +1,237 @@
+#!perl
+
+################################################################################
+=comment
+
+Perl Weekly Challenge 265
+=========================
+
+TASK #2
+-------
+*Completing Word*
+
+Submitted by: Mohammad Sajid Anwar
+
+You are given a string, $str containing alphnumeric characters and array of
+strings (alphabetic characters only), @str.
+
+Write a script to find the shortest completing word. If none found return empty
+string.
+
+ A completing word is a word that contains all the letters in the given
+ string, ignoring space and number. If a letter appeared more than once in
+ the given string then it must appear the same number or more in the word.
+
+Example 1
+
+ Input: $str = 'aBc 11c'
+ @str = ('accbbb', 'abc', 'abbc')
+ Output: 'accbbb'
+
+ The given string contains following, ignoring case and number:
+ a 1 times
+ b 1 times
+ c 2 times
+
+ The only string in the given array that satisfies the condition is 'accbbb'.
+
+Example 2
+
+ Input: $str = 'Da2 abc'
+ @str = ('abcm', 'baacd', 'abaadc')
+ Output: 'baacd'
+
+ The given string contains following, ignoring case and number:
+ a 2 times
+ b 1 times
+ c 1 times
+ d 1 times
+
+ The are 2 strings in the given array that satisfies the condition:
+ 'baacd' and 'abaadc'.
+
+ Shortest of the two is 'baacd'
+
+Example 3
+
+ Input: $str = 'JB 007'
+ @str = ('jj', 'bb', 'bjb')
+ Output: 'bjb'
+
+ The given string contains following, ignoring case and number:
+ j 1 times
+ b 1 times
+
+ The only string in the given array that satisfies the condition is 'bjb'.
+
+=cut
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2024 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=comment
+
+Interface
+---------
+1. If no command-line arguments are given, the test suite is run. Otherwise:
+2. The string $str is entered as a named argument on the command-line.
+3. Strings of the list @str are entered as unnamed arguments on the command-
+ line.
+
+Assumptions
+-----------
+1. From the Examples, it appears that case is ignored when searching for a com-
+ pleting word.
+2. If there are two or more shortest completing words, choose the first (lowest)
+ by ascending alphabetical order.
+
+=cut
+#===============================================================================
+
+use v5.32.1; # Enables strictures
+use warnings;
+use Const::Fast;
+use Getopt::Long;
+use Test::More;
+
+const my $USAGE => <<END;
+Usage:
+ perl $0 [--str=<Str>] [<strs> ...]
+ perl $0
+
+ --str=<Str> String of alphnumeric chars and/or whitespace
+ [<strs> ...] List of strings of alphabetic characters only
+END
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\nChallenge 265, Task #2: Completing Word (Perl)\n\n";
+}
+
+#===============================================================================
+MAIN:
+#===============================================================================
+{
+ if (scalar @ARGV == 0)
+ {
+ run_tests();
+ }
+ else
+ {
+ my ($str, $strs) = parse_command_line();
+
+ print "Input: \$str = '$str'\n";
+ printf " \@strs = (%s)\n", join ', ', map { "'$_'" } @$strs;
+
+ my $word = find_completing_word( $str, $strs );
+
+ print "Output: '$word'\n";
+ }
+}
+
+#-------------------------------------------------------------------------------
+sub find_completing_word
+#-------------------------------------------------------------------------------
+{
+ my ($str, $strings) = @_;
+ my %required;
+
+ for my $char (split //, $str)
+ {
+ ++$required{ lc $char } if $char =~ / ^ [[:alpha:]] $ /x;
+ }
+
+ my @candidates;
+
+ L_STRINGS: for my $string (@$strings)
+ {
+ my %chars;
+ ++$chars{ lc() } for split //, $string;
+
+ for my $key (keys %required)
+ {
+ next L_STRINGS unless exists $chars{ $key } &&
+ $chars{ $key } >= $required{ $key };
+ }
+
+ push @candidates, $string;
+ }
+
+ @candidates = sort { length $a <=> length $b || $a cmp $b } @candidates;
+
+ return scalar @candidates > 0 ? $candidates[ 0 ] : '';
+}
+
+#-------------------------------------------------------------------------------
+sub parse_command_line
+#-------------------------------------------------------------------------------
+{
+ my ($str);
+
+ GetOptions
+ (
+ 'str=s' => \$str,
+ ) or error( 'Invalid command-line arguments' );
+
+ $str // error( 'Missing $str' );
+ $str =~ / ^ [A-Za-z0-9\s]* $ /x
+ or error( qq["$str" is not a valid \$str] );
+
+ my @strs = @ARGV;
+
+ / ^ [A-Za-z]* $ /x or error( qq["$_" is not a valid value for \@strs] )
+ for @strs;
+
+ return ($str, \@strs);
+}
+
+#-------------------------------------------------------------------------------
+sub run_tests
+#-------------------------------------------------------------------------------
+{
+ print "Running the test suite\n";
+
+ while (my $line = <DATA>)
+ {
+ chomp $line;
+
+ my ($test_name, $str, $strs_str, $expected) = split / \| /x, $line;
+
+ for ($test_name, $str, $strs_str, $expected)
+ {
+ s/ ^ \s+ //x;
+ s/ \s+ $ //x;
+ }
+
+ my @str = split / \s+ /x, $strs_str;
+ my $word = find_completing_word( $str, \@str );
+
+ is $word, $expected, $test_name;
+ }
+
+ done_testing;
+}
+
+#-------------------------------------------------------------------------------
+sub error
+#-------------------------------------------------------------------------------
+{
+ my ($message) = @_;
+
+ die "ERROR: $message\n$USAGE";
+}
+
+################################################################################
+
+__DATA__
+Example 1|aBc 11c|accbbb abc abbc |accbbb
+Example 2|Da2 abc|abcm baacd abaadc|baacd
+Example 3|JB 007 |jj bb bjb |bjb
+Sort |Da2 abc|abcm baacdf baacde|baacde
+None |Abcd 4f|abc df acf |
diff --git a/challenge-265/athanasius/raku/ch-1.raku b/challenge-265/athanasius/raku/ch-1.raku
new file mode 100644
index 0000000000..08fed70d94
--- /dev/null
+++ b/challenge-265/athanasius/raku/ch-1.raku
@@ -0,0 +1,170 @@
+use v6d;
+
+################################################################################
+=begin comment
+
+Perl Weekly Challenge 265
+=========================
+
+TASK #1
+-------
+*33% Appearance*
+
+Submitted by: Mohammad Sajid Anwar
+
+You are given an array of integers, @ints.
+
+Write a script to find an integer in the given array that appeared 33% or more.
+If more than one found, return the smallest. If none found then return undef.
+
+Example 1
+
+ Input: @ints = (1,2,3,3,3,3,4,2)
+ Output: 3
+
+ 1 appeared 1 times.
+ 2 appeared 2 times.
+ 3 appeared 4 times.
+
+ 3 appeared 50% (>33%) in the given array.
+
+Example 2
+
+ Input: @ints = (1,1)
+ Output: 1
+
+ 1 appeared 2 times.
+
+ 1 appeared 100% (>33%) in the given array.
+
+Example 3
+
+ Input: @ints = (1,2,3)
+ Output: 1
+
+ 1 appeared 1 times.
+ 2 appeared 1 times.
+ 3 appeared 1 times.
+
+ Since all three appeared 33.3% (>33%) in the given array.
+ We pick the smallest of all.
+
+=end comment
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2024 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=begin comment
+
+Interface
+---------
+1. If no command-line arguments are given, the test suite is run. Otherwise:
+2. A list of one or more integers is given on the command-line.
+3. If the first integer is negative, it must be preceded by "--" to indicate
+ that it is not a command-line flag.
+
+=end comment
+#===============================================================================
+
+use Test;
+
+my Rat constant THRESHOLD = 0.33;
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ "\nChallenge 265, Task #1: 33% Appearance (Raku)\n".put;
+}
+
+#===============================================================================
+multi sub MAIN
+(
+ #| A non-empty list of integers
+
+ *@ints where { .elems > 0 && .all ~~ Int:D }
+)
+#===============================================================================
+{
+ "Input: \@ints = (%s)\n".printf: @ints.join: ',';
+
+ my Int $solution = solve( @ints );
+
+ "Output: %s\n".printf: $solution.defined ?? $solution !! 'undef (= none)';
+}
+
+#===============================================================================
+multi sub MAIN() # No input: run the test suite
+#===============================================================================
+{
+ run-tests();
+}
+
+#-------------------------------------------------------------------------------
+sub solve( List:D[Int:D] $ints --> Int )
+#-------------------------------------------------------------------------------
+{
+ my UInt $target = ($ints.elems * THRESHOLD).ceiling;
+ my Int %count;
+ ++%count{ $_ } for @$ints;
+ my Int @candidates = %count<>:k.grep( { %count{ $_ } >= $target } )\
+ .map: { .Int };
+
+ return @candidates.elems > 0 ?? @candidates.min !! Int;
+}
+
+#-------------------------------------------------------------------------------
+sub run-tests()
+#-------------------------------------------------------------------------------
+{
+ 'Running the test suite'.put;
+
+ for test-data.lines -> Str $line
+ {
+ my Str ($test-name, $ints-str, $expected-str) = $line.split: / \| /;
+
+ for $test-name, $ints-str, $expected-str
+ {
+ s/ ^ \s+ //;
+ s/ \s+ $ //;
+ }
+
+ my Int @ints = $ints-str.split( / \s+ /, :skip-empty )\
+ .map: { .Int };
+ my Int $solution = solve( @ints );
+ my Int $expected = $expected-str.chars > 0 ?? $expected-str.Int !! Int;
+
+ is $solution, $expected, $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| 1 2 3 3 3 3 4 2| 3
+ Example 2| 1 1 | 1
+ Example 3| 1 2 3 | 1
+ None | 1 2 3 4 |
+ Negatives|-1 0 -2 1 -2 -1 |-2
+ END
+}
+
+################################################################################
diff --git a/challenge-265/athanasius/raku/ch-2.raku b/challenge-265/athanasius/raku/ch-2.raku
new file mode 100644
index 0000000000..ff332ea237
--- /dev/null
+++ b/challenge-265/athanasius/raku/ch-2.raku
@@ -0,0 +1,212 @@
+use v6d;
+
+################################################################################
+=begin comment
+
+Perl Weekly Challenge 265
+=========================
+
+TASK #2
+-------
+*Completing Word*
+
+Submitted by: Mohammad Sajid Anwar
+
+You are given a string, $str containing alphnumeric characters and array of
+strings (alphabetic characters only), @str.
+
+Write a script to find the shortest completing word. If none found return empty
+string.
+
+ A completing word is a word that contains all the letters in the given
+ string, ignoring space and number. If a letter appeared more than once in
+ the given string then it must appear the same number or more in the word.
+
+Example 1
+
+ Input: $str = 'aBc 11c'
+ @str = ('accbbb', 'abc', 'abbc')
+ Output: 'accbbb'
+
+ The given string contains following, ignoring case and number:
+ a 1 times
+ b 1 times
+ c 2 times
+
+ The only string in the given array that satisfies the condition is 'accbbb'.
+
+Example 2
+
+ Input: $str = 'Da2 abc'
+ @str = ('abcm', 'baacd', 'abaadc')
+ Output: 'baacd'
+
+ The given string contains following, ignoring case and number:
+ a 2 times
+ b 1 times
+ c 1 times
+ d 1 times
+
+ The are 2 strings in the given array that satisfies the condition:
+ 'baacd' and 'abaadc'.
+
+ Shortest of the two is 'baacd'
+
+Example 3
+
+ Input: $str = 'JB 007'
+ @str = ('jj', 'bb', 'bjb')
+ Output: 'bjb'
+
+ The given string contains following, ignoring case and number:
+ j 1 times
+ b 1 times
+
+ The only string in the given array that satisfies the condition is 'bjb'.
+
+=end comment
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2024 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=begin comment
+
+Interface
+---------
+1. If no command-line arguments are given, the test suite is run. Otherwise:
+2. The string $str is entered as a named argument on the command-line.
+3. Strings of the list @str are entered as unnamed arguments on the command-
+ line.
+
+Assumptions
+-----------
+1. From the Examples, it appears that case is ignored when searching for a com-
+ pleting word.
+2. If there are two or more shortest completing words, choose the first (lowest)
+ by ascending alphabetical order.
+
+=end comment
+#===============================================================================
+
+use Test;
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ "\nChallenge 265, Task #2: Completing Word (Raku)\n".put;
+}
+
+#===============================================================================
+multi sub MAIN
+(
+ #| String of alphnumeric chars and/or whitespace
+
+ Str:D :$str where { $str ~~ / ^ <[ \w \s ] - [ _ ]>* $ / },
+
+ #| List of strings of alphabetic characters only
+
+ *@strs where { .all ~~ / ^ <[ a .. z A .. Z ]>* $ / }
+)
+#===============================================================================
+{
+ "Input: \$str = '$str'".put;
+ " \@strs = (%s)\n".printf: @strs.map( { "'$_'" } ).join: ', ';
+
+ my Str $word = find-completing-word( $str, @strs );
+
+ "Output: '$word'".put;
+}
+
+#===============================================================================
+multi sub MAIN() # No input: run the test suite
+#===============================================================================
+{
+ run-tests();
+}
+
+#-------------------------------------------------------------------------------
+sub find-completing-word( Str:D $str, List:D[Str:D] $strings --> Str:D )
+#-------------------------------------------------------------------------------
+{
+ my UInt %required;
+
+ for $str.split( '', :skip-empty ) -> Str $char
+ {
+ ++%required{ $char.lc } if $char ~~ / ^ <.alpha> $ /;
+ }
+
+ my Str @candidates;
+
+ L-STRINGS: for @$strings -> Str $string
+ {
+ my UInt %chars;
+ ++%chars{ .lc } for $string.split: '', :skip-empty;
+
+ for %required<>:k -> Str $key
+ {
+ next L-STRINGS unless %chars{ $key }:exists &&
+ %chars{ $key } >= %required{ $key };
+ }
+
+ @candidates.push: $string;
+ }
+
+ @candidates .= sort: { .chars, .Str };
+
+ return @candidates.elems > 0 ?? @candidates[ 0 ] !! '';
+}
+
+#-------------------------------------------------------------------------------
+sub run-tests()
+#-------------------------------------------------------------------------------
+{
+ 'Running the test suite'.put;
+
+ for test-data.lines -> Str $line
+ {
+ my Str ($test-name, $str, $strs-str, $expected) = $line.split: / \| /;
+
+ for $test-name, $str, $strs-str, $expected
+ {
+ s/ ^ \s+ //;
+ s/ \s+ $ //;
+ }
+
+ my Str @str = $strs-str.split: / \s+ /, :skip-empty;
+ my Str $word = find-completing-word( $str, @str );
+
+ is $word, $expected, $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|aBc 11c|accbbb abc abbc |accbbb
+ Example 2|Da2 abc|abcm baacd abaadc|baacd
+ Example 3|JB 007 |jj bb bjb |bjb
+ Sort |Da2 abc|abcm baacdf baacde|baacde
+ None |Abcd 4f|abc df acf |
+ END
+}
+
+################################################################################