http://qs1969.pair.com?node_id=393064

in reply to Iterating over combinations

When I was working on this, I noticed revdiablo was generating all combinations of all sizes. I came up with a working solution to find only combinations of the desired size though it wasn't very elegant. I then sat down to figure out how I could make it generic for any size combinations (without having found this node) and came up with the following:
```#!/usr/bin/perl
use strict;
use warnings;

my \$iter = combo( 5 , 1 .. 50  );
while ( my @combo = \$iter->() ) {
print "@combo\n";
}

sub combo {
my \$by = shift;
return sub { () } if ! \$by || \$by =~ /\D/ || @_ < \$by;
my @list = @_;

my @position = (0 .. \$by - 2, \$by - 2);
my @stop     = @list - \$by .. \$#list;
my \$end_pos  = \$#position;
my \$done     = undef;

return sub {
return () if \$done;
my \$cur = \$end_pos;
{
if ( ++\$position[ \$cur ] > \$stop[ \$cur ] ) {
\$position[ --\$cur ]++;
redo if \$position[ \$cur ] > \$stop[ \$cur ];
my \$new_pos = \$position[ \$cur ];
@position[ \$cur .. \$end_pos ] = \$new_pos .. \$new_pos +
+ \$by;
}
}
\$done = 1 if \$position[0] == \$stop[0];
return @list[ @position ];
}
}