t3/simon

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(", ") ~ ")";
}

Correctness

The code produces correct results.

Consistency

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.

Clarity of intent

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.

Algorithmic efficiency

This solution does the usual recursive search through the solution space, same as many others.

Idiomatic use of Perl 6

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. :-)

Brevity

Short.