aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad S Anwar <Mohammad.Anwar@yahoo.com>2022-03-18 10:20:13 +0000
committerGitHub <noreply@github.com>2022-03-18 10:20:13 +0000
commit1126cd9625e63f7b3c3da8524c727e7d0999f960 (patch)
tree0b59d779b5c7ec3f19f8f5da4031f264d46d9c6f
parent2d76c7fd9b2a3faa24f5352e58624962e665b9d9 (diff)
parent60ac6343e116e10fdd362a859f0bea7aa9094ff6 (diff)
downloadperlweeklychallenge-club-1126cd9625e63f7b3c3da8524c727e7d0999f960.tar.gz
perlweeklychallenge-club-1126cd9625e63f7b3c3da8524c727e7d0999f960.tar.bz2
perlweeklychallenge-club-1126cd9625e63f7b3c3da8524c727e7d0999f960.zip
Merge pull request #5789 from PerlMonk-Athanasius/branch-for-challenge-156
Perl & Raku solutions to Tasks 1 & 2 of the Weekly Challenge 156
-rw-r--r--challenge-156/athanasius/perl/ch-1.pl149
-rw-r--r--challenge-156/athanasius/perl/ch-2.pl253
-rw-r--r--challenge-156/athanasius/raku/ch-1.raku122
-rw-r--r--challenge-156/athanasius/raku/ch-2.raku254
4 files changed, 778 insertions, 0 deletions
diff --git a/challenge-156/athanasius/perl/ch-1.pl b/challenge-156/athanasius/perl/ch-1.pl
new file mode 100644
index 0000000000..285ba4872e
--- /dev/null
+++ b/challenge-156/athanasius/perl/ch-1.pl
@@ -0,0 +1,149 @@
+#!perl
+
+###############################################################################
+=comment
+
+Perl Weekly Challenge 156
+=========================
+
+TASK #1
+-------
+*Pernicious Numbers*
+
+Submitted by: Mohammad S Anwar
+
+Write a script to permute first 10 Pernicious Numbers.
+
+ A pernicious number is a positive integer which has prime number of ones in
+ its binary representation.
+
+The first pernicious number is 3 since binary representation of 3 = (11) and
+1 + 1 = 2, which is a prime.
+
+Expected Output
+
+ 3, 5, 6, 7, 9, 10, 11, 12, 13, 14
+
+=cut
+###############################################################################
+
+#--------------------------------------#
+# Copyright © 2022 PerlMonk Athanasius #
+#--------------------------------------#
+
+#==============================================================================
+=comment
+
+Interface
+---------
+Although the Task specifies a target of 10, I have extended the solution to
+accept any target integer value greater than 0; but if no argument is supplied
+on the command line, the target defaults to 10.
+
+Table
+-----
+The first 100 Pernicious Numbers [1, 2]:
+
+ 3, 5, 6, 7, 9, 10, 11, 12, 13, 14,
+ 17, 18, 19, 20, 21, 22, 24, 25, 26, 28,
+ 31, 33, 34, 35, 36, 37, 38, 40, 41, 42,
+ 44, 47, 48, 49, 50, 52, 55, 56, 59, 61,
+ 62, 65, 66, 67, 68, 69, 70, 72, 73, 74,
+ 76, 79, 80, 81, 82, 84, 87, 88, 91, 93,
+ 94, 96, 97, 98, 100, 103, 104, 107, 109, 110,
+ 112, 115, 117, 118, 121, 122, 124, 127, 129, 130,
+ 131, 132, 133, 134, 136, 137, 138, 140, 143, 144,
+ 145, 146, 148, 151, 152, 155, 157, 158, 160, 161
+
+Algorithm
+---------
+The natural numbers, in ascending order, are filtered as follows:
+ - each natural number n is converted to its binary representation b;
+ - the 1-digits in b are counted;
+ - if the count is a primary number, n is recorded as a pernicious number;
+ - the filtering process continues until the number of pernicious numbers found
+ is equal to the given target.
+
+References
+----------
+[1] "A052294 Pernicious numbers: numbers with a prime number of 1's in their
+ binary expansion.", The On-Line Encyclopedia of Integer Sequences,
+ https://oeis.org/A052294
+[2] Iain Fox, "Table of n, a(n) for n = 1..10000",
+ https://oeis.org/A052294/b052294.txt
+[3] "Pernicious number", Wikipedia,
+ https://en.wikipedia.org/wiki/Pernicious_number
+
+=cut
+#==============================================================================
+
+use strict;
+use warnings;
+use Const::Fast;
+use ntheory qw( is_prime );
+use Regexp::Common qw( number );
+
+const my $TARGET => 10;
+const my $USAGE =>
+"Usage:
+ perl $0 [<target>]
+
+ [<target>] The required output size [default: $TARGET]\n";
+
+#------------------------------------------------------------------------------
+BEGIN
+#------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\nChallenge 156, Task #1: Pernicious Numbers (Perl)\n\n";
+}
+
+#==============================================================================
+MAIN:
+#==============================================================================
+{
+ my $target = parse_command_line();
+
+ print "The first $target Pernicious Numbers:\n";
+
+ my @pernicious;
+
+ for (my $n = 1; scalar @pernicious < $target; ++$n)
+ {
+ my $bin = sprintf '%b', $n; # Convert to binary
+ my $ones = $bin =~ tr/1//; # Count the ones
+
+ push @pernicious, $n if is_prime( $ones );
+ }
+
+ printf "%s\n", join ', ', @pernicious;
+}
+
+#------------------------------------------------------------------------------
+sub parse_command_line
+#------------------------------------------------------------------------------
+{
+ my $args = scalar @ARGV;
+ 0 <= $args <= 1 or error( 'Expected no more than 1 command line ' .
+ "argument, found $args" );
+
+ my $target = $args == 0 ? $TARGET : $ARGV[ 0 ];
+
+ $target =~ / ^ $RE{num}{int} $ /x
+ or error( qq["$target" is not a valid integer] );
+
+ $target > 0 or error( 'Target must be greater than 0' );
+
+ return $target;
+}
+
+#------------------------------------------------------------------------------
+sub error
+#------------------------------------------------------------------------------
+{
+ my ($message) = @_;
+
+ die "ERROR: $message\n$USAGE";
+}
+
+###############################################################################
diff --git a/challenge-156/athanasius/perl/ch-2.pl b/challenge-156/athanasius/perl/ch-2.pl
new file mode 100644
index 0000000000..0e316974da
--- /dev/null
+++ b/challenge-156/athanasius/perl/ch-2.pl
@@ -0,0 +1,253 @@
+#!perl
+
+###############################################################################
+=comment
+
+Perl Weekly Challenge 156
+=========================
+
+TASK #2
+-------
+*Weird Number*
+
+Submitted by: Mohammad S Anwar
+
+You are given number, $n > 0.
+
+Write a script to find out if the given number is a Weird Number.
+
+According to [ https://en.wikipedia.org/wiki/Weird_number |Wikipedia], it is
+defined as:
+
+ The sum of the proper divisors (divisors including 1 but not itself) of the
+ number is greater than the number, but no subset of those divisors sums to
+ the number itself.
+
+Example 1:
+
+ Input: $n = 12
+ Output: 0
+
+ Since the proper divisors of 12 are 1, 2, 3, 4, and 6, which sum to 16; but
+ 2 + 4 + 6 = 12.
+
+Example 2:
+
+ Input: $n = 70
+ Output: 1
+
+ As the proper divisors of 70 are 1, 2, 5, 7, 10, 14, and 35; these sum to 74,
+ but no subset of these sums to 70.
+
+=cut
+###############################################################################
+
+#--------------------------------------#
+# Copyright © 2022 PerlMonk Athanasius #
+#--------------------------------------#
+
+#==============================================================================
+=comment
+
+Interface
+---------
+If the constant $VERBOSE is set to a true value (the default), the output is
+followed by an explanation of why the given n is or is not a weird number.
+
+Table
+-----
+The first 100 Weird Numbers [1], [2]:
+ 70, 836, 4030, 5830, 7192, 7912, 9272, 10430, 10570, 10792,
+10990, 11410, 11690, 12110, 12530, 12670, 13370, 13510, 13790, 13930,
+14770, 15610, 15890, 16030, 16310, 16730, 16870, 17272, 17570, 17990,
+18410, 18830, 18970, 19390, 19670, 19810, 20510, 21490, 21770, 21910,
+22190, 23170, 23590, 24290, 24430, 24710, 25130, 25690, 26110, 26530,
+26810, 27230, 27790, 28070, 28630, 29330, 29470, 30170, 30310, 30730,
+31010, 31430, 31990, 32270, 32410, 32690, 33530, 34090, 34370, 34930,
+35210, 35630, 36470, 36610, 37870, 38290, 38990, 39410, 39830, 39970,
+40390, 41090, 41510, 41930, 42070, 42490, 42910, 43190, 43330, 44170,
+44870, 45010, 45290, 45356, 45710, 46130, 46270, 47110, 47390, 47810
+
+Algorithm
+---------
+1. To determine whether n is an abundant number, its proper factors are first
+ generated using the divisors() subroutine from the CPAN Module ntheory
+ (a.k.a. Math::Prime::Util). divisors() returns all the divisors, so the last
+ divisor (viz., n itself) must be removed. The proper divisors are then
+ summed, and the sum compared to n.
+
+2. To determine whether n is a semiperfect number, subsets of n's proper
+ factors are summed and the results compared with n. Subsets are generated by
+ the combinations() subroutine from the CPAN module Algorithm::Combinatorics,
+ which takes 2 arguments: the set from which the subsets are to be drawn, and
+ k, the number of elements in the required subsets.
+
+ Let the set of proper factors be F. We note that the required values of k
+ begin at 3 and end at |F| - 1, because:
+ - for any proper divisor d of n, d < n, so if k = 1, sum = d, which is < n;
+ - the largest possible proper divisor d0 of n is n/2, and the next largest,
+ d1, is < d0, so for k = 2 any sum = (d0 + d1) must be less than n;
+ - n is already known to be abundant, so if k = |F| then the sum > n.
+
+References
+----------
+[1] "A006037 Weird numbers: abundant (A005101) but not pseudoperfect
+ (A005835).", The On-Line Encyclopedia of Integer Sequences,
+ https://oeis.org/A006037
+[2] Amiram Eldar, "Table of n, a(n) for n = 1..10000",
+ https://oeis.org/A006037/b006037.txt
+[3] "Weird number", Wikipedia, https://en.wikipedia.org/wiki/Weird_number
+
+=cut
+#==============================================================================
+
+use strict;
+use warnings;
+use Algorithm::Combinatorics qw( combinations );
+use Const::Fast;
+use ntheory qw( divisors );
+use Regexp::Common qw( number );
+
+const my $VERBOSE => 1;
+const my $USAGE =>
+"Usage:
+ perl $0 <n>
+
+ <n> A natural number\n";
+
+#------------------------------------------------------------------------------
+BEGIN
+#------------------------------------------------------------------------------
+{
+ $| = 1;
+ print "\nChallenge 156, Task #2: Weird Number (Perl)\n\n";
+}
+
+#==============================================================================
+MAIN:
+#==============================================================================
+{
+ my $n = parse_command_line();
+
+ print "Input: \$n = $n\n";
+
+ my @divisors = divisors( $n );
+ pop @divisors; # Remove $n to leave only *proper* divisors
+
+ my $sum = 0;
+ $sum += $_ for @divisors;
+
+ if ($sum <= $n) # n is not an abundant number
+ {
+ print "Output: 0\n";
+ explain_failure_deficient( $n, \@divisors, $sum ) if $VERBOSE;
+ }
+ else # n is an abundant number
+ {
+ my $subset = find_subset( $n, \@divisors);
+
+ if (scalar @$subset > 0) # n is a semiperfect number
+ {
+ print "Output: 0\n";
+ explain_failure_semi( $n, \@divisors, $sum, $subset ) if $VERBOSE;
+ }
+ else # n is not a semiperfect number
+ {
+ print "Output: 1\n";
+ explain_success( $n, \@divisors, $sum ) if $VERBOSE;
+ }
+ }
+}
+
+#------------------------------------------------------------------------------
+sub find_subset
+#------------------------------------------------------------------------------
+{
+ my ($n, $divisors) = @_;
+ my @subset;
+
+ L_OUTER:
+ for my $k (3 .. $#$divisors)
+ {
+ my $iter = combinations( $divisors, $k );
+
+ while (my $comb = $iter->next)
+ {
+ my $sum = 0;
+ $sum += $_ for @$comb;
+
+ if ($sum == $n)
+ {
+ @subset = @$comb;
+ last L_OUTER;
+ }
+ }
+ }
+
+ return \@subset;
+}
+
+#------------------------------------------------------------------------------
+sub explain_failure_deficient # Not weird because not abundant
+#------------------------------------------------------------------------------
+{
+ my ($n, $divisors, $sum) = @_;
+
+ printf "\nExplanation:\nThe proper divisors of %d (%s) sum to %d," .
+ "\ntherefore %d is not weird because it is not abundant\n",
+ $n, join( ', ', @$divisors ), $sum, $n;
+}
+
+#------------------------------------------------------------------------------
+sub explain_failure_semi # Not weird: abundant but semiperfect
+#------------------------------------------------------------------------------
+{
+ my ($n, $divisors, $sum, $subset) = @_;
+
+ printf "\nExplanation:\nThe proper divisors of %d (%s) sum to %d," .
+ "\nbut the subset (%s) of these proper divisors sums to %d," .
+ "\ntherefore %d is not weird because, although abundant, " .
+ "it is also semiperfect\n",
+ $n, join( ', ', @$divisors ), $sum, join( ', ', @$subset ), $n, $n;
+}
+
+#------------------------------------------------------------------------------
+sub explain_success # Weird: abundant and not semiperfect
+#------------------------------------------------------------------------------
+{
+ my ($n, $divisors, $sum) = @_;
+
+ printf "\nExplanation:\nThe proper divisors of %d (%s) sum to %d," .
+ "\nand no subset of these proper divisors sums to %d," .
+ "\ntherefore %d is weird because it is abundant but not " .
+ "semiperfect\n",
+ $n, join( ', ', @$divisors ), $sum, $n, $n;
+}
+
+#------------------------------------------------------------------------------
+sub parse_command_line
+#------------------------------------------------------------------------------
+{
+ my $args = scalar @ARGV;
+ $args == 1 or error( "Expected 1 command line argument, found $args" );
+
+ my $n = $ARGV[ 0 ];
+
+ $n =~ / ^ $RE{num}{int} $ /x
+ or error( qq["$n" is not a valid integer] );
+
+ $n > 0 or error( 'n must be greater than 0' );
+
+ return $n;
+}
+
+#------------------------------------------------------------------------------
+sub error
+#------------------------------------------------------------------------------
+{
+ my ($message) = @_;
+
+ die "ERROR: $message\n$USAGE";
+}
+
+###############################################################################
diff --git a/challenge-156/athanasius/raku/ch-1.raku b/challenge-156/athanasius/raku/ch-1.raku
new file mode 100644
index 0000000000..d71f4c6237
--- /dev/null
+++ b/challenge-156/athanasius/raku/ch-1.raku
@@ -0,0 +1,122 @@
+use v6d;
+
+###############################################################################
+=begin comment
+
+Perl Weekly Challenge 156
+=========================
+
+TASK #1
+-------
+*Pernicious Numbers*
+
+Submitted by: Mohammad S Anwar
+
+Write a script to permute first 10 Pernicious Numbers.
+
+ A pernicious number is a positive integer which has prime number of ones in
+ its binary representation.
+
+The first pernicious number is 3 since binary representation of 3 = (11) and
+1 + 1 = 2, which is a prime.
+
+Expected Output
+
+ 3, 5, 6, 7, 9, 10, 11, 12, 13, 14
+
+=end comment
+###############################################################################
+
+#--------------------------------------#
+# Copyright © 2022 PerlMonk Athanasius #
+#--------------------------------------#
+
+#==============================================================================
+=begin comment
+
+Interface
+---------
+Although the Task specifies a target of 10, I have extended the solution to
+accept any target integer value greater than 0; but if no argument is supplied
+on the command line, the target defaults to 10.
+
+Table
+-----
+The first 100 Pernicious Numbers [1, 2]:
+
+ 3, 5, 6, 7, 9, 10, 11, 12, 13, 14,
+ 17, 18, 19, 20, 21, 22, 24, 25, 26, 28,
+ 31, 33, 34, 35, 36, 37, 38, 40, 41, 42,
+ 44, 47, 48, 49, 50, 52, 55, 56, 59, 61,
+ 62, 65, 66, 67, 68, 69, 70, 72, 73, 74,
+ 76, 79, 80, 81, 82, 84, 87, 88, 91, 93,
+ 94, 96, 97, 98, 100, 103, 104, 107, 109, 110,
+ 112, 115, 117, 118, 121, 122, 124, 127, 129, 130,
+ 131, 132, 133, 134, 136, 137, 138, 140, 143, 144,
+ 145, 146, 148, 151, 152, 155, 157, 158, 160, 161
+
+Algorithm
+---------
+The natural numbers, in ascending order, are filtered as follows:
+ - each natural number n is converted to its binary representation b;
+ - the 1-digits in b are counted;
+ - if the count is a primary number, n is recorded as a pernicious number.
+ - the filtering process continues until the number of pernicious numbers found
+ is equal to the given target.
+
+References
+----------
+[1] "A052294 Pernicious numbers: numbers with a prime number of 1's in their
+ binary expansion.", The On-Line Encyclopedia of Integer Sequences,
+ https://oeis.org/A052294
+[2] Iain Fox, "Table of n, a(n) for n = 1..10000",
+ https://oeis.org/A052294/b052294.txt
+[3] "Pernicious number", Wikipedia,
+ https://en.wikipedia.org/wiki/Pernicious_number
+
+=end comment
+#==============================================================================
+
+my UInt constant $TARGET = 10;
+
+#------------------------------------------------------------------------------
+BEGIN
+#------------------------------------------------------------------------------
+{
+ "\nChallenge 156, Task #1: Pernicious Numbers (Raku)\n".put;
+}
+
+#==============================================================================
+sub MAIN
+(
+ UInt:D $target where * > 0 = $TARGET #= The required output size
+)
+#==============================================================================
+{
+ "The first $target Pernicious Numbers:".put;
+
+ my UInt @pernicious;
+
+ loop (my UInt $n = 1; +@pernicious < $target; ++$n)
+ {
+ my Str $bin = '%b'.sprintf: $n; # Convert to binary
+ my UInt $ones = +$bin.comb: '1'; # Count the ones
+
+ @pernicious.push: $n if $ones.is-prime;
+ }
+
+ "%s\n".printf: @pernicious.join: ', ';
+}
+
+#------------------------------------------------------------------------------
+sub USAGE()
+#------------------------------------------------------------------------------
+{
+ my Str $usage = $*USAGE;
+
+ $usage ~~ s/ ($*PROGRAM-NAME) /raku $0/;
+
+ $usage.put;
+}
+
+##############################################################################
diff --git a/challenge-156/athanasius/raku/ch-2.raku b/challenge-156/athanasius/raku/ch-2.raku
new file mode 100644
index 0000000000..aade096465
--- /dev/null
+++ b/challenge-156/athanasius/raku/ch-2.raku
@@ -0,0 +1,254 @@
+use v6d;
+
+###############################################################################
+=begin comment
+
+Perl Weekly Challenge 156
+=========================
+
+TASK #2
+-------
+*Weird Number*
+
+Submitted by: Mohammad S Anwar
+
+You are given number, $n > 0.
+
+Write a script to find out if the given number is a Weird Number.
+
+According to [ https://en.wikipedia.org/wiki/Weird_number |Wikipedia], it is
+defined as:
+
+ The sum of the proper divisors (divisors including 1 but not itself) of the
+ number is greater than the number, but no subset of those divisors sums to
+ the number itself.
+
+Example 1:
+
+ Input: $n = 12
+ Output: 0
+
+ Since the proper divisors of 12 are 1, 2, 3, 4, and 6, which sum to 16; but
+ 2 + 4 + 6 = 12.
+
+Example 2:
+
+ Input: $n = 70
+ Output: 1
+
+ As the proper divisors of 70 are 1, 2, 5, 7, 10, 14, and 35; these sum to 74,
+ but no subset of these sums to 70.
+
+=end comment
+###############################################################################
+
+#--------------------------------------#
+# Copyright © 2022 PerlMonk Athanasius #
+#--------------------------------------#
+
+#==============================================================================
+=begin comment
+
+Interface
+---------
+If the constant $VERBOSE is set to True, (the default), the output is followed
+by an explanation of why the given n is or is not a weird number.
+
+Table
+-----
+The first 100 Weird Numbers [1], [2]:
+ 70, 836, 4030, 5830, 7192, 7912, 9272, 10430, 10570, 10792,
+10990, 11410, 11690, 12110, 12530, 12670, 13370, 13510, 13790, 13930,
+14770, 15610, 15890, 16030, 16310, 16730, 16870, 17272, 17570, 17990,
+18410, 18830, 18970, 19390, 19670, 19810, 20510, 21490, 21770, 21910,
+22190, 23170, 23590, 24290, 24430, 24710, 25130, 25690, 26110, 26530,
+26810, 27230, 27790, 28070, 28630, 29330, 29470, 30170, 30310, 30730,
+31010, 31430, 31990, 32270, 32410, 32690, 33530, 34090, 34370, 34930,
+35210, 35630, 36470, 36610, 37870, 38290, 38990, 39410, 39830, 39970,
+40390, 41090, 41510, 41930, 42070, 42490, 42910, 43190, 43330, 44170,
+44870, 45010, 45290, 45356, 45710, 46130, 46270, 47110, 47390, 47810
+
+Algorithm
+---------
+1. To determine whether n is an abundant number, its proper factors are first
+ generated by filtering integers in the range 1 to ⌊$n / 2⌋ using Raku's
+ built-in divisibility operator, "%%".
+
+2. To determine whether n is a semiperfect number, subsets of n's proper
+ factors are summed and the results compared with n. Subsets are generated by
+ Raku's built-in combinations() method. The argument k to this method
+ specifies the number of elements in the required subsets.
+
+ Let the set of proper factors be F. We note that the required values of k
+ begin at 3 and end at |F| - 1, because:
+ - for any proper divisor d of n, d < n, so if k = 1, sum = d, which is < n;
+ - the largest possible proper divisor d0 of n is n/2, and the next largest,
+ d1, is < d0, so for k = 2 any sum = (d0 + d1) must be less than n;
+ - n is already known to be abundant, so if k = |F| then the sum > n.
+
+References
+----------
+[1] "A006037 Weird numbers: abundant (A005101) but not pseudoperfect
+ (A005835).", The On-Line Encyclopedia of Integer Sequences,
+ https://oeis.org/A006037
+[2] Amiram Eldar, "Table of n, a(n) for n = 1..10000",
+ https://oeis.org/A006037/b006037.txt
+[3] "Weird number", Wikipedia, https://en.wikipedia.org/wiki/Weird_number
+
+=end comment
+#==============================================================================
+
+my Bool constant $VERBOSE = True;
+
+#------------------------------------------------------------------------------
+BEGIN
+#------------------------------------------------------------------------------
+{
+ "\nChallenge 156, Task #2: Weird Number (Raku)\n".put;
+}
+
+#==============================================================================
+sub MAIN
+(
+ UInt:D $n where * > 0 #= A natural number
+)
+#==============================================================================
+{
+ "Input: \$n = $n".put;
+
+ my UInt @divisors = proper-divisors( $n );
+ my UInt $sum = [+] @divisors;
+
+ if $sum <= $n # n is not an abundant number
+ {
+ 'Output: 0'.put;
+ explain-failure-deficient( $n, @divisors, $sum ) if $VERBOSE;
+ }
+ else # n is an abundant number
+ {
+ my $subset = find-subset( $n, @divisors);
+
+ if +$subset > 0 # n is a semiperfect number
+ {
+ 'Output: 0'.put;
+ explain-failure-semi( $n, @divisors, $sum, $subset ) if $VERBOSE;
+ }
+ else # n is not a semiperfect number
+ {
+ 'Output: 1'.put;
+ explain-success( $n, @divisors, $sum ) if $VERBOSE;
+ }
+ }
+}
+
+#------------------------------------------------------------------------------
+sub find-subset
+(
+ UInt:D $n where * > 0, #= A natural number
+ Array:D[UInt:D] $divisors #= The proper divisors of n
+--> Array:D[UInt:D] #= A subset (if any) of the proper
+ #= divisors that sums to n
+)
+#------------------------------------------------------------------------------
+{
+ my UInt @subset;
+
+ # start = 3: max proper divisor of n is n/2, next lower is < n/2, so sum of
+ # any 2 divisors must be < n
+ # end: sum of all divisors is known to be > n, so end is |n| - 1
+
+ L-OUTER:
+ for 3 ..^ +$divisors -> UInt $k
+ {
+ for $divisors.combinations: $k -> List $comb
+ {
+ my UInt $sum = [+] $comb;
+
+ if $sum == $n
+ {
+ @subset = @$comb;
+ last L-OUTER;
+ }
+ }
+ }
+
+ return @subset;
+}
+
+#------------------------------------------------------------------------------
+sub proper-divisors
+(
+ UInt:D $n where * > 0 #= A natural number
+--> List:D[UInt:D] #= The proper divisors of n
+)
+#------------------------------------------------------------------------------
+{
+ my UInt @divisors;
+
+ for 1 .. ($n / 2).floor -> UInt $d
+ {
+ @divisors.push: $d if $n %% $d;
+ }
+
+ return @divisors;
+}
+
+#------------------------------------------------------------------------------
+sub explain-failure-deficient # Not weird because not abundant
+(
+ UInt:D $n where * > 0, #= A natural number
+ Array:D[UInt:D] $divisors, #= The proper divisors of n
+ UInt:D $sum #= The sum of the proper divisors
+)
+#------------------------------------------------------------------------------
+{
+ ("\nExplanation:\nThe proper divisors of %d (%s) sum to %d," ~
+ "\ntherefore %d is not weird because it is not abundant\n").printf:
+ $n, $divisors.join( ', ' ), $sum, $n;
+}
+
+#------------------------------------------------------------------------------
+sub explain-failure-semi # Not weird: abundant but semiperfect
+(
+ UInt:D $n where * > 0, #= A natural number
+ Array:D[UInt:D] $divisors, #= The proper divisors of n
+ UInt:D $sum, #= The sum of the proper divisors
+ Array:D[UInt:D] $subset #= A subset of the proper divisors
+ #= that sums to n
+)
+#------------------------------------------------------------------------------
+{
+ ("\nExplanation:\nThe proper divisors of %d (%s) sum to %d," ~
+ "\nbut the subset (%s) of these proper divisors sums to %d," ~
+ "\ntherefore %d is not weird because, although abundant, " ~
+ "it is also semiperfect\n").printf:
+ $n, $divisors.join( ', ' ), $sum, $subset.join( ', ' ), $n, $n;
+}
+
+#------------------------------------------------------------------------------
+sub explain-success # Weird: abundant and not semiperfect
+(
+ UInt:D $n where * > 0, #= A natural number
+ Array:D[UInt:D] $divisors, #= The proper divisors of n
+ UInt:D $sum, #= The sum of the proper divisors
+)
+#------------------------------------------------------------------------------
+{
+ ("\nExplanation:\nThe proper divisors of %d (%s) sum to %d," ~
+ "\nand no subset of these proper divisors sums to %d," ~
+ "\ntherefore %d is weird because it is abundant but not " ~
+ "semiperfect\n").printf: $n, $divisors.join( ', ' ), $sum, $n, $n;
+}
+
+#------------------------------------------------------------------------------
+sub USAGE()
+#------------------------------------------------------------------------------
+{
+ my Str $usage = $*USAGE;
+
+ $usage ~~ s/ ($*PROGRAM-NAME) /raku $0/;
+
+ $usage.put;
+}
+
+##############################################################################