Download the raw code.
use v6;
#make a BFS over all possible addition chains
sub chain(@c, $l, $n) {
for @c Z 1..* {for (@c) Z (($^a) xx $^b) -> $x, $y {
my $s = $x + $y;
if ($l) {
last if $s <= @c[*-1];
my $c = chain(@($s,@c), $l-1, $n) and return $c;
} else {
last if $s < $n;
$s == $n and return (@($s, @c));
}
}}
return Bool::False;
}
sub MAIN(Int $n) {
$n > 0 or say "Argument must be positive." and return;
$n == 1 and say "(1)" and return;
my $min = (log($n)/log(2)).ceiling - 1;
my $solution = ();
until ($solution = chain((1,), $min++, $n)) {};
say "(" ~$solution.reverse.join(", ") ~ ")";
}
The code produces correct results.
The return value of Bool::False comes as a bit of a consistency surprise
after having returned Lists so far. return () (or just return) would
return a list (retaining consistency), which would still evaluate to false
(retaining current semantics).
The for loops were used without parentheses, but the if and until
conditions got parentheses, for some reason.
The parentheses around @c are not needed.
Given the throwing-around of list operators, one-letter variables, parameter
placeholders, stream-of-consciousness and and or statements, the code is
still refreshingly clear.
This solution does the usual recursive search through the solution space, same as many others.
There's no need to initialize $solution to an empty Parcel before the
until loop, when that empty Parcel is never used anyway — you could
declare the variable in the loop condition instead:
until (my $solution = chain((1,), $min++, $n)) {};
Could've saved one more line there. :-)
Short.