TL;DR

On with TASK #2 from The Weekly Challenge #156. Enjoy!

# The challenge

You are given number, $n > 0. Write a script to find out if the given number is a Weird Number. According to 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.  # The questions Whatâ€™s in the challenges this week? Is there anything that calls for lazy, brutey force attacks, or is it just me? # The solution As anticipated, Iâ€™m very lazy this week. This totally reflects in the Perl solution, where I summon three different modules to get the job done: #!/usr/bin/env perl use v5.24; use warnings; use experimental 'signatures'; no warnings 'experimental::signatures'; use FindBin '$Bin';
use lib "$Bin/local/lib/perl5"; use Algorithm::Knapsack; use ntheory 'divisors'; use List::Util 'sum'; say$_, ' ', is_weird($_) for (@ARGV ? @ARGV : (12, 70)); sub is_weird ($n) {
my @divs = reverse divisors($n); shift @divs if @divs > 1; return 0 if$n >= sum @divs;
my $ks = Algorithm::Knapsack->new(capacity =>$n, weights => \@divs);
$ks->compute; for my$solution ($ks->solutions) { my$sum = sum @divs[$solution->@*]; return 0 if$sum == $n; } return 1; }  Need the divisors? There you go, ntheory. Need to arrange good approximations? There you go, Algorithm::Knapsack. Need to do sums? There you go, List::Util. Need some glue? There you go, Perl. The Raku translation shows even more lazyness. While some stuff is included just like the batteries, like a handy sum method, looking for proper divisors and using the knapsack algorithm is harder because a very lazy search did not make anything stand out. So I opted for implementing stuff just to minimize the waste of time for looking a pre-made solution. Iâ€™m ashamed. Here it is: #!/usr/bin/env raku use v6; sub MAIN (*@args) { my @inputs = @args ?? |@args !! (12, 70); @inputs.map({ put$_, ' ', is-weird($_); }); } sub proper-divisors (Int:D$n) { (1..($n/2)).grep:$n %% * }

sub is-weird (Int:D $n) { my @divs = proper-divisors($n);
return 0 if @divs.sum <= $n; loop { my$sum = @divs.sum;
return 0 if $sum ==$n;
return 1 if $sum <$n;
my $ms = @divs.pop; my$target = $n -$ms;
for (^(2 ** @divs.elems)).reverse -> $k is copy { my$sum = 0;
my $i = 0; while$k > 0 {
$sum += @divs[$i] if $k +& 1; return 0 if$target == $sum; ++$i;
\$k +>= 1;
}
}
}
}


I guess the implementation if is-weird is closer to what I was expected to do. I mean, what I think I might have been expected to do, i.e. code a solution specific to the problem. Whatever, the Perl solution is a solution too.

Anyway, here Iâ€™m trying to find out if thereâ€™s an arrangement that sums up exactly to the input number, except that Iâ€™m trying to bail out early if conditions donâ€™t apply any more. This is obtained by considering the sums with the highest number(s) first, eliminating them on the way. When we end up with a residual list whose sum is lower than the target number, thereâ€™s no way to select a subset that sums exactly to that and we can safely return early. Not too much of an optimization but still.

The proper-divisors function finally gave me the occasion to use the whatever variable in a grep. So far I could not manage to get it right, but as you can see Iâ€™m still trying.

You might have observed that Iâ€™m using the first singular person a lot here, instead of a more inclusive first plural version. This is because I take full responsibility for not thinking too much about the solution to the challenge, and I donâ€™t want to make it appear like itâ€™s somebody elseâ€™s fault too.

Letâ€™s hope the best for people in Ukraine, and the rest of the places that are in a war!

Comments? Octodon, , GitHub, Reddit, or drop me a line!