aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPerlMonk-Athanasius <PerlMonk.Athanasius@gmail.com>2023-11-27 00:24:40 +1000
committerPerlMonk-Athanasius <PerlMonk.Athanasius@gmail.com>2023-11-27 00:24:40 +1000
commit264d3db16ad6a1123e1ff019830de79f3e59b04e (patch)
treeee5771d2b335ad0fa44fba4961be7cbc021399db
parenta21c8ec426c8151d3b00e2e7e17d220992bea80f (diff)
downloadperlweeklychallenge-club-264d3db16ad6a1123e1ff019830de79f3e59b04e.tar.gz
perlweeklychallenge-club-264d3db16ad6a1123e1ff019830de79f3e59b04e.tar.bz2
perlweeklychallenge-club-264d3db16ad6a1123e1ff019830de79f3e59b04e.zip
Perl & Raku solutions to Tasks 1 & 2 for Week 244
-rw-r--r--challenge-244/athanasius/perl/ch-1.pl163
-rw-r--r--challenge-244/athanasius/perl/ch-2.pl199
-rw-r--r--challenge-244/athanasius/raku/ch-1.raku160
-rw-r--r--challenge-244/athanasius/raku/ch-2.raku192
4 files changed, 714 insertions, 0 deletions
diff --git a/challenge-244/athanasius/perl/ch-1.pl b/challenge-244/athanasius/perl/ch-1.pl
new file mode 100644
index 0000000000..a0d2df4ff8
--- /dev/null
+++ b/challenge-244/athanasius/perl/ch-1.pl
@@ -0,0 +1,163 @@
+#!perl
+
+################################################################################
+=comment
+
+Perl Weekly Challenge 244
+=========================
+
+TASK #1
+-------
+*Count Smaller*
+
+Submitted by: Mohammad S Anwar
+
+You are given an array of integers.
+
+Write a script to calculate the number of integers smaller than the integer at
+each index.
+
+Example 1
+
+ Input: @int = (8, 1, 2, 2, 3)
+ Output: (4, 0, 1, 1, 3)
+
+ For index = 0, count of elements less 8 is 4.
+ For index = 1, count of elements less 1 is 0.
+ For index = 2, count of elements less 2 is 1.
+ For index = 3, count of elements less 2 is 1.
+ For index = 4, count of elements less 3 is 3.
+
+Example 2
+
+ Input: @int = (6, 5, 4, 8)
+ Output: (2, 1, 0, 3)
+
+Example 3
+
+ Input: @int = (2, 2, 2)
+ Output: (0, 0, 0)
+
+=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 List::MoreUtils qw( first_index );
+use Regexp::Common qw( number );
+use Test::More;
+
+const my $USAGE =>
+"Usage:
+ perl $0 [<int> ...]
+ perl $0
+
+ [<int> ...] A list of integers\n";
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\nChallenge 244, Task #1: Count Smaller (Perl)\n\n";
+}
+
+#===============================================================================
+MAIN:
+#===============================================================================
+{
+ if (scalar @ARGV == 0)
+ {
+ run_tests();
+ }
+ else
+ {
+ my @int = @ARGV;
+
+ for (@int)
+ {
+ / ^ $RE{num}{int} $ /x or error( qq["$_" is not a valid integer] );
+ }
+
+ printf "Input: \@int = (%s)\n", join ', ', @int;
+
+ my $out = count_smaller( \@int );
+
+ printf "Output: (%s)\n", join ', ', @$out;
+ }
+}
+
+#-------------------------------------------------------------------------------
+sub count_smaller
+#-------------------------------------------------------------------------------
+{
+ my ($ints) = @_;
+ my @sorted = sort { $a <=> $b } @$ints;
+ my @out;
+
+ for my $int (@$ints)
+ {
+ push @out, first_index { $_ == $int } @sorted;
+ }
+
+ return \@out;
+}
+
+#-------------------------------------------------------------------------------
+sub run_tests
+#-------------------------------------------------------------------------------
+{
+ print "Running the test suite\n";
+
+ while (my $line = <DATA>)
+ {
+ chomp $line;
+
+ my ($test_name, $int_str, $exp_str) = split / \| /x, $line;
+
+ for ($test_name, $int_str, $exp_str)
+ {
+ s/ ^ \s+ //x;
+ s/ \s+ $ //x;
+ }
+
+ my @int = split / \s+ /x, $int_str;
+ my $out = count_smaller( \@int );
+ my @exp = split / \s+ /x, $exp_str;
+
+ is_deeply $out, \@exp, $test_name;
+ }
+
+ done_testing;
+}
+
+#-------------------------------------------------------------------------------
+sub error
+#-------------------------------------------------------------------------------
+{
+ my ($message) = @_;
+
+ die "ERROR: $message\n$USAGE";
+}
+
+################################################################################
+
+__DATA__
+Example 1|8 1 2 2 3|4 0 1 1 3
+Example 2|6 5 4 8 |2 1 0 3
+Example 3|2 2 2 |0 0 0
diff --git a/challenge-244/athanasius/perl/ch-2.pl b/challenge-244/athanasius/perl/ch-2.pl
new file mode 100644
index 0000000000..a07fe21754
--- /dev/null
+++ b/challenge-244/athanasius/perl/ch-2.pl
@@ -0,0 +1,199 @@
+#!perl
+
+################################################################################
+=comment
+
+Perl Weekly Challenge 244
+=========================
+
+TASK #2
+-------
+*Group Hero*
+
+Submitted by: Mohammad S Anwar
+
+You are given an array of integers representing the strength.
+
+Write a script to return the sum of the powers of all possible combinations;
+power is defined as the square of the largest number in a sequence, multiplied
+by the smallest.
+
+Example 1
+
+ Input: @nums = (2, 1, 4)
+ Output: 141
+
+ Group 1: (2) => square(max(2)) * min(2) => 4 * 2 => 8
+ Group 2: (1) => square(max(1)) * min(1) => 1 * 1 => 1
+ Group 3: (4) => square(max(4)) * min(4) => 16 * 4 => 64
+ Group 4: (2,1) => square(max(2,1)) * min(2,1) => 4 * 1 => 4
+ Group 5: (2,4) => square(max(2,4)) * min(2,4) => 16 * 2 => 32
+ Group 6: (1,4) => square(max(1,4)) * min(1,4) => 16 * 1 => 16
+ Group 7: (2,1,4) => square(max(2,1,4)) * min(2,1,4) => 16 * 1 => 16
+
+ Sum: 8 + 1 + 64 + 4 + 32 + 16 + 16 => 141
+
+=cut
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2023 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=comment
+
+Assumptions
+-----------
+1. Duplicates are allowed in the input list.
+2. Combinations are unordered and unique, but may contain duplicates. So, (1, 2)
+ and (2, 1) are the same combination, BUT (1, 2) and (1, 2, 2) are different
+ combinations (and so must be counted separately).
+
+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 List::Util qw( any max min uniqnum );
+use Math::Prime::Util qw( forcomb );
+use Regexp::Common qw( number );
+use Test::More;
+
+const my $USAGE =>
+"Usage:
+ perl $0 [<nums> ...]
+ perl $0
+
+ [<nums> ...] A list of integers\n";
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\nChallenge 244, Task #2: Group Hero (Perl)\n\n";
+}
+
+#===============================================================================
+MAIN:
+#===============================================================================
+{
+ if (scalar @ARGV == 0)
+ {
+ run_tests();
+ }
+ else
+ {
+ my @nums = @ARGV;
+
+ / ^ $RE{num}{int} $ /x or error( qq["$_" is not a valid integer] )
+ for @nums;
+
+ printf "Input: \@nums = (%s)\n", join ', ', @nums;
+
+ my $sum = power_sum( \@nums );
+
+ print "Output: $sum\n";
+ }
+}
+
+#-------------------------------------------------------------------------------
+sub power_sum
+#-------------------------------------------------------------------------------
+{
+ my ($nums) = @_;
+ my @set = sort { $a <=> $b } uniqnum @$nums;
+ my @combs;
+ my %groups;
+
+ forcomb { push @combs, [ @set[ @_ ] ] } @set;
+
+ for my $comb (@combs)
+ {
+ next if scalar @$comb == 0;
+
+ my $key = join '|', @$comb;
+
+ $groups{ $key } = power( $comb );
+ }
+
+ my $sum = 0;
+ my %counts;
+ ++$counts{ $_ } for @$nums;
+
+ for my $key (keys %groups)
+ {
+ my @comb = split / \| /x, $key;
+ my $mult = 1;
+
+ for my $num (keys %counts)
+ {
+ $mult *= $counts{ $num } if any { $num == $_ } @comb;
+ }
+
+ $sum += $groups{ $key } * $mult;
+ }
+
+ return $sum;
+}
+
+#-------------------------------------------------------------------------------
+sub power
+#-------------------------------------------------------------------------------
+{
+ my ($comb) = @_;
+ my @nums = @$comb;
+ my $max = max @nums;
+ my $min = min @nums;
+
+ return $max * $max * $min;
+}
+
+#-------------------------------------------------------------------------------
+sub run_tests
+#-------------------------------------------------------------------------------
+{
+ print "Running the test suite\n";
+
+ while (my $line = <DATA>)
+ {
+ chomp $line;
+
+ my ($test_name, $nums_str, $exp_str) = split / \| /x, $line;
+
+ for ($test_name, $nums_str, $exp_str)
+ {
+ s/ ^ \s+ //x;
+ s/ \s+ $ //x;
+ }
+
+ my @nums = split / \s+ /x, $nums_str;
+ my $sum = power_sum( \@nums );
+
+ is $sum, $exp_str, $test_name;
+ }
+
+ done_testing;
+}
+
+#-------------------------------------------------------------------------------
+sub error
+#-------------------------------------------------------------------------------
+{
+ my ($message) = @_;
+
+ die "ERROR: $message\n$USAGE";
+}
+
+################################################################################
+
+__DATA__
+Example 1 | 2 1 4 |141
+Multiples 1| 1 1 2 2 | 34
+Multiples 2| 2 1 4 1 2 1|315
diff --git a/challenge-244/athanasius/raku/ch-1.raku b/challenge-244/athanasius/raku/ch-1.raku
new file mode 100644
index 0000000000..4b564c3cde
--- /dev/null
+++ b/challenge-244/athanasius/raku/ch-1.raku
@@ -0,0 +1,160 @@
+use v6d;
+
+################################################################################
+=begin comment
+
+Perl Weekly Challenge 244
+=========================
+
+TASK #1
+-------
+*Count Smaller*
+
+Submitted by: Mohammad S Anwar
+
+You are given an array of integers.
+
+Write a script to calculate the number of integers smaller than the integer at
+each index.
+
+Example 1
+
+ Input: @int = (8, 1, 2, 2, 3)
+ Output: (4, 0, 1, 1, 3)
+
+ For index = 0, count of elements less 8 is 4.
+ For index = 1, count of elements less 1 is 0.
+ For index = 2, count of elements less 2 is 1.
+ For index = 3, count of elements less 2 is 1.
+ For index = 4, count of elements less 3 is 3.
+
+Example 2
+
+ Input: @int = (6, 5, 4, 8)
+ Output: (2, 1, 0, 3)
+
+Example 3
+
+ Input: @int = (2, 2, 2)
+ Output: (0, 0, 0)
+
+=end comment
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2023 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=begin comment
+
+Interface
+---------
+1. If no command-line arguments are given, the test suite is run. Otherwise:
+2. 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;
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ "\nChallenge 244, Task #1: Count Smaller (Raku)\n".put;
+}
+
+#===============================================================================
+multi sub MAIN
+(
+ *@int where { .elems > 0 && .all ~~ Int:D } #= A list of integers
+)
+#===============================================================================
+{
+ "Input: \@int = (%s)\n".printf: @int.join: ', ';
+
+ my UInt @out = count-smaller( @int );
+
+ "Output: (%s)\n"\.printf: @out.join: ', ';
+}
+
+#===============================================================================
+multi sub MAIN() # No input: run the test suite
+#===============================================================================
+{
+ run-tests();
+}
+
+#-------------------------------------------------------------------------------
+sub count-smaller( List:D[Int:D] $ints --> List:D[UInt:D] )
+#-------------------------------------------------------------------------------
+{
+ my Int @sorted = $ints.sort;
+ my UInt @out;
+ @out.push: @sorted.first: * == $_, :k for @$ints;
+
+ return @out;
+}
+
+#-------------------------------------------------------------------------------
+sub run-tests()
+#-------------------------------------------------------------------------------
+{
+ 'Running the test suite'.put;
+
+ for test-data.lines -> Str $line
+ {
+ my Str ($test-name, $int-str, $exp-str) = $line.split: / \| /;
+
+ for $test-name, $int-str, $exp-str
+ {
+ s/ ^ \s+ //;
+ s/ \s+ $ //;
+ }
+
+ my Int @int = $int-str.split( / \s+ / ).map: { .Int };
+ my UInt @out = count-smaller( @int );
+ my UInt @exp = $exp-str.split( / \s+ / ).map: { .Int };
+
+ is-deeply @out, @exp, $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|8 1 2 2 3|4 0 1 1 3
+ Example 2|6 5 4 8 |2 1 0 3
+ Example 3|2 2 2 |0 0 0
+ END
+}
+
+################################################################################
diff --git a/challenge-244/athanasius/raku/ch-2.raku b/challenge-244/athanasius/raku/ch-2.raku
new file mode 100644
index 0000000000..c1e927c869
--- /dev/null
+++ b/challenge-244/athanasius/raku/ch-2.raku
@@ -0,0 +1,192 @@
+use v6d;
+
+################################################################################
+=begin comment
+
+Perl Weekly Challenge 244
+=========================
+
+TASK #2
+-------
+*Group Hero*
+
+Submitted by: Mohammad S Anwar
+
+You are given an array of integers representing the strength.
+
+Write a script to return the sum of the powers of all possible combinations;
+power is defined as the square of the largest number in a sequence, multiplied
+by the smallest.
+
+Example 1
+
+ Input: @nums = (2, 1, 4)
+ Output: 141
+
+ Group 1: (2) => square(max(2)) * min(2) => 4 * 2 => 8
+ Group 2: (1) => square(max(1)) * min(1) => 1 * 1 => 1
+ Group 3: (4) => square(max(4)) * min(4) => 16 * 4 => 64
+ Group 4: (2,1) => square(max(2,1)) * min(2,1) => 4 * 1 => 4
+ Group 5: (2,4) => square(max(2,4)) * min(2,4) => 16 * 2 => 32
+ Group 6: (1,4) => square(max(1,4)) * min(1,4) => 16 * 1 => 16
+ Group 7: (2,1,4) => square(max(2,1,4)) * min(2,1,4) => 16 * 1 => 16
+
+ Sum: 8 + 1 + 64 + 4 + 32 + 16 + 16 => 141
+
+=end comment
+################################################################################
+
+#--------------------------------------#
+# Copyright © 2023 PerlMonk Athanasius #
+#--------------------------------------#
+
+#===============================================================================
+=begin comment
+
+Assumptions
+-----------
+1. Duplicates are allowed in the input list.
+2. Combinations are unordered and unique, but may contain duplicates. So, (1, 2)
+ and (2, 1) are the same combination, BUT (1, 2) and (1, 2, 2) are different
+ combinations (and so must be counted separately).
+
+Interface
+---------
+If no command-line arguments are given, the test suite is run.
+
+=end comment
+#===============================================================================
+
+use Test;
+
+#-------------------------------------------------------------------------------
+BEGIN
+#-------------------------------------------------------------------------------
+{
+ "\nChallenge 244, Task #2: Group Hero (Raku)\n".put;
+}
+
+#===============================================================================
+multi sub MAIN
+(
+ *@nums where { .elems > 0 && .all ~~ Int:D } #= A list of integers
+)
+#===============================================================================
+{
+ "Input: \@nums = (%s)\n".printf: @nums.join: ', ';
+
+ my Int $sum = power-sum( @nums );
+
+ "Output: $sum".put;
+}
+
+#===============================================================================
+multi sub MAIN() # No input: run the test suite
+#===============================================================================
+{
+ run-tests();
+}
+
+#-------------------------------------------------------------------------------
+sub power-sum( List:D[Int:D] $nums --> Int:D )
+#-------------------------------------------------------------------------------
+{
+ my Int %groups{Set[Int]};
+
+ for $nums.combinations: 1 .. * -> List $comb
+ {
+ my $set = Set[Int].new: $comb.map: { .Int };
+
+ %groups{ $set } = power( $set );
+ }
+
+ my UInt %counts{Int};
+ ++%counts{ $_ } for @$nums;
+
+ my Int $sum = 0;
+
+ for %groups.keys -> Set[Int] $comb
+ {
+ my UInt $multiplier = 1;
+
+ for %counts.keys -> Int $num
+ {
+ $multiplier *= %counts{ $num } if $num.Int ∈ $comb;
+ }
+
+ $sum += %groups{ $comb } * $multiplier;
+ }
+
+ return $sum;
+}
+
+#-------------------------------------------------------------------------------
+sub power( Set:D[Int:D] $comb --> Int:D )
+#-------------------------------------------------------------------------------
+{
+ my Int @nums = $comb.keys;
+ my Int $max = @nums.max;
+ my Int $min = @nums.min;
+
+ return $max² * $min;
+}
+
+#-------------------------------------------------------------------------------
+sub run-tests()
+#-------------------------------------------------------------------------------
+{
+ 'Running the test suite'.put;
+
+ for test-data.lines -> Str $line
+ {
+ my Str ($test-name, $nums-str, $exp-str) = $line.split: / \| /;
+
+ for $test-name, $nums-str, $exp-str
+ {
+ s/ ^ \s+ //;
+ s/ \s+ $ //;
+ }
+
+ my Int @nums = $nums-str.split( / \s+ / ).map: { .Int };
+ my Int $sum = power-sum( @nums );
+
+ is $sum, $exp-str.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 |2 1 4 |141
+ Multiples 1|1 1 2 2 | 34
+ Multiples 2|2 1 4 1 2 1|315
+ END
+}
+
+################################################################################