From 264d3db16ad6a1123e1ff019830de79f3e59b04e Mon Sep 17 00:00:00 2001 From: PerlMonk-Athanasius Date: Mon, 27 Nov 2023 00:24:40 +1000 Subject: Perl & Raku solutions to Tasks 1 & 2 for Week 244 --- challenge-244/athanasius/perl/ch-1.pl | 163 ++++++++++++++++++++++++++ challenge-244/athanasius/perl/ch-2.pl | 199 ++++++++++++++++++++++++++++++++ challenge-244/athanasius/raku/ch-1.raku | 160 +++++++++++++++++++++++++ challenge-244/athanasius/raku/ch-2.raku | 192 ++++++++++++++++++++++++++++++ 4 files changed, 714 insertions(+) create mode 100644 challenge-244/athanasius/perl/ch-1.pl create mode 100644 challenge-244/athanasius/perl/ch-2.pl create mode 100644 challenge-244/athanasius/raku/ch-1.raku create mode 100644 challenge-244/athanasius/raku/ch-2.raku 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 [ ...] + perl $0 + + [ ...] 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 = ) + { + 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 [ ...] + perl $0 + + [ ...] 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 = ) + { + 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 +} + +################################################################################ -- cgit