<?xml version="1.0" encoding="windows-1252"?>
<node id="557196" title="Re^3: Finding all Combinations" created="2006-06-23 10:21:49" updated="2006-06-23 06:21:49">
<type id="11">
note</type>
<author id="533863">
roboticus</author>
<data>
<field name="doctext">
[id://180961]:&lt;p&gt;
I've finally &lt;i&gt;got&lt;/i&gt; it!  Thanks for the help you posted on your scratchpad.  After a few hours of study, it finally paid off.  I've commented it to describe how it works, and made a few changes to fix a minor bug, and remove some code that is never executed, and removed a state variable:&lt;p&gt;
&lt;code&gt;
#------------------------------------------------------------
# Return an iterator of all possible combinations (of all
# lengths) of a set of symbols with the constraint that each
# symbol in each result is less than the symbol to its right.
#
sub combo {

    # The symbols we draw our results from:
    my @list = @_;

    # The trivial case
    return sub { ( ) } if ! @_;

    # Persistent state for the closure
    my (@position, # Last set of symbol indices generated
        @stop);    # Last set possible for $by symbols

    # Start by telling iterator that it just finished
    # (next=1) all results of 0 digits.
    my ($by, $next) = (0, 1);

    return sub {
&lt;/code&gt;&lt;strike&gt;&lt;code&gt;
        # We're done after we've returned a list of all symbols
        return () if @position == @list;
&lt;/code&gt;&lt;/strike&gt;&lt;code&gt;
        if ( $next ) {
            # We finished all combos of size $by, now do $by+1
            $by++;
&lt;/code&gt;&lt;b&gt;&lt;code&gt;
            # If new size is larger than list, we're done!
            return () if $by &gt; @list;
&lt;/code&gt;&lt;/b&gt;&lt;code&gt;

            # Start with leftmost $by symbols (except last,
            # which is preincremented before use)
            @position = (0 .. $by - 2, $by - 2);

            # Our stop condition is when we've returned the
            # rightmost $by symbols
            @stop = @list - $by .. $#list;

            $next = undef;
        }

        # Start by trying to advance the rightmost digit
        my $cur = $#position;
        {   # **** redo comes back here! ****

            # Advance current digit to next symbol
            if ( ++$position[ $cur ] &gt; $stop[ $cur ] ) {

                # Keep trying next-most rightmost digit
                # until we find one that's not 'stopped'
                $position[ --$cur ]++;
                redo if $position[ $cur ] &gt; $stop[ $cur ];

                # Reset digits to right of current digit to
                # the leftmost possible positions
                my $new_pos = $position[ $cur ];
                @position[$cur .. $#position] = $new_pos .. $new_pos+$by;
            }
        }

        # Advance to next result size when we return last
        # possible result of this size
        $next = $position[0]==$stop[0];

        return @list[ @position ];
    }
}
&lt;/code&gt;
Thanks again! I learned a &lt;b&gt;&lt;i&gt;lot&lt;/i&gt;&lt;/b&gt; from this exercise.&lt;p&gt;
&lt;b&gt;UPDATE:&lt;/b&gt; I just tweaked the code a bit to make it check for done less frequently so it'll run a bit quicker.  It munges up the code listing a bit though.  Is there a better way to edit the code so it's obvious without interspersing download links?&lt;p&gt;
--roboticus</field>
<field name="root_node">
128286</field>
<field name="parent_node">
394168</field>
</data>
</node>
