Download the raw code.
#!/usr/local/bin/perl6
# Find the first N numbers that are the sum of (at least) two distinct
# cubes with lazy evaluation.
sub sum_of_cube_finder
{
my (%sums, @pend, %pend);
my (Int $n1, Int $n1c, Int $n2, Int $sum);
$n1 = 1;
return sub
{
while True {
$n1++;
$n1c = $n1 ** 3;
# Return pending elements as long as $n1 ** 3 is larger.
# This ensures we don't return a larger number ahead of
# a smaller number that might be found with the current $n1.
@pend = %pend.keys.sort: { $^a <=> $^b };
while @pend.elems && $n1c > @pend[0] {
$sum = shift @pend;
%pend.delete($sum);
return $sum, %sums{$sum};
}
# Garbage collect any sums that will never be matched
# because $n1 ** 3 got too big.
for %sums.keys { %sums.delete($_) if $_ < $n1c };
# Look for $n1 ** 3 + $n2 ** 3, for all $n2 smaller than $n1.
# If we detect a repeated sum, queue it up for later return.
for 1 ..^ $n1 -> $n2 {
$sum = $n1c + $n2 ** 3;
%sums.push($sum => "$n1 ** 3 + $n2 ** 3");
%pend{$sum} = 1 if (%sums{$sum}.elems > 1);
}
}
}
}
sub MAIN($count)
{
my (Int $sum, $cubes);
my $next_sum_of_cubes = sum_of_cube_finder;
for 1 .. $count {
($sum, $cubes) = $next_sum_of_cubes();
say "$sum = ", $cubes.join(" = ");
}
}
The first five lines of output are correct, then a large number of cubes are not found, starting with
39312 = 34 ** 3 + 2 ** 3 = 33 ** 3 + 15 ** 3
The problem (or at least one problem) seems to be that $n1
is incremented at
least once between finding two target numbers, so this algorithm cannot find
two different target numbers that have the same $n1 ** 3
component.
The layout is a mixture of K&R and Allman style.
The vertical layout is a bit fragemented too, the inner loop in
sum_of_cube_finder
has more blank lines than the other loops, for
no apparent reason.
It is easy to follow the line of thought behind this solution, though the iterator-style control flow makes it unnecessarily hard to reason about the considered sums of cubes, and thus about correctness.
Honorable use of list assignment (sometimes we forget our Perl 5 heritage),
anonymous subs, Hash.push
and MAIN
.
A more seasoned Perl 6 programmer might have used gather
/take
and lazy lists instead of the custom iterator..
Doesn't go all out with brevity, but instead spaces itself out a bit. Still, not a lot of code for what it does.